XXXX introduce drv_sectohz

   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 QLogic Corporation.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  29  */
  30 
  31 #include <sys/conf.h>
  32 #include <sys/ddi.h>
  33 #include <sys/stat.h>
  34 #include <sys/pci.h>
  35 #include <sys/sunddi.h>
  36 #include <sys/modctl.h>
  37 #include <sys/file.h>
  38 #include <sys/cred.h>
  39 #include <sys/byteorder.h>
  40 #include <sys/atomic.h>
  41 #include <sys/scsi/scsi.h>
  42 
  43 #include <sys/stmf_defines.h>
  44 #include <sys/fct_defines.h>
  45 #include <sys/stmf.h>
  46 #include <sys/stmf_ioctl.h>
  47 #include <sys/portif.h>
  48 #include <sys/fct.h>
  49 
  50 #include "qlt.h"
  51 #include "qlt_dma.h"
  52 #include "qlt_ioctl.h"
  53 #include "qlt_open.h"
  54 
  55 static int qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
  56 static int qlt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
  57 static void qlt_enable_intr(qlt_state_t *);
  58 static void qlt_disable_intr(qlt_state_t *);
  59 static fct_status_t qlt_reset_chip(qlt_state_t *qlt);
  60 static fct_status_t qlt_download_fw(qlt_state_t *qlt);
  61 static fct_status_t qlt_load_risc_ram(qlt_state_t *qlt, uint32_t *host_addr,
  62     uint32_t word_count, uint32_t risc_addr);
  63 static fct_status_t qlt_raw_mailbox_command(qlt_state_t *qlt);
  64 static mbox_cmd_t *qlt_alloc_mailbox_command(qlt_state_t *qlt,
  65                                         uint32_t dma_size);
  66 void qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
  67 static fct_status_t qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp);
  68 static uint_t qlt_isr(caddr_t arg, caddr_t arg2);
  69 static fct_status_t qlt_firmware_dump(fct_local_port_t *port,
  70     stmf_state_change_info_t *ssci);
  71 static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot);
  72 static void qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp);
  73 static void qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio);
  74 static void qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp);
  75 static void qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp);
  76 static void qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp);
  77 static void qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
  78 static void qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt,
  79     uint8_t *rsp);
  80 static void qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp);
  81 static void qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp);
  82 static void qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp);
  83 static fct_status_t qlt_read_nvram(qlt_state_t *qlt);
  84 static void qlt_verify_fw(qlt_state_t *qlt);
  85 static void qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp);
  86 fct_status_t qlt_port_start(caddr_t arg);
  87 fct_status_t qlt_port_stop(caddr_t arg);
  88 fct_status_t qlt_port_online(qlt_state_t *qlt);
  89 fct_status_t qlt_port_offline(qlt_state_t *qlt);
  90 static fct_status_t qlt_get_link_info(fct_local_port_t *port,
  91     fct_link_info_t *li);
  92 static void qlt_ctl(struct fct_local_port *port, int cmd, void *arg);
  93 static fct_status_t qlt_force_lip(qlt_state_t *);
  94 static fct_status_t qlt_do_flogi(struct fct_local_port *port,
  95                                                 fct_flogi_xchg_t *fx);
  96 void qlt_handle_atio_queue_update(qlt_state_t *qlt);
  97 void qlt_handle_resp_queue_update(qlt_state_t *qlt);
  98 fct_status_t qlt_register_remote_port(fct_local_port_t *port,
  99     fct_remote_port_t *rp, fct_cmd_t *login);
 100 fct_status_t qlt_deregister_remote_port(fct_local_port_t *port,
 101     fct_remote_port_t *rp);
 102 fct_status_t qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags);
 103 fct_status_t qlt_send_els_response(qlt_state_t *qlt, fct_cmd_t *cmd);
 104 fct_status_t qlt_send_abts_response(qlt_state_t *qlt,
 105     fct_cmd_t *cmd, int terminate);
 106 static void qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot);
 107 int qlt_set_uniq_flag(uint16_t *ptr, uint16_t setf, uint16_t abortf);
 108 fct_status_t qlt_abort_cmd(struct fct_local_port *port,
 109     fct_cmd_t *cmd, uint32_t flags);
 110 fct_status_t qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd);
 111 fct_status_t qlt_abort_purex(qlt_state_t *qlt, fct_cmd_t *cmd);
 112 fct_status_t qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd);
 113 fct_status_t qlt_send_cmd(fct_cmd_t *cmd);
 114 fct_status_t qlt_send_els(qlt_state_t *qlt, fct_cmd_t *cmd);
 115 fct_status_t qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd);
 116 fct_status_t qlt_xfer_scsi_data(fct_cmd_t *cmd,
 117     stmf_data_buf_t *dbuf, uint32_t ioflags);
 118 fct_status_t qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd);
 119 static void qlt_handle_ct_completion(qlt_state_t *qlt, uint8_t *rsp);
 120 static void qlt_release_intr(qlt_state_t *qlt);
 121 static int qlt_setup_interrupts(qlt_state_t *qlt);
 122 static void qlt_destroy_mutex(qlt_state_t *qlt);
 123 
 124 static fct_status_t qlt_read_risc_ram(qlt_state_t *qlt, uint32_t addr,
 125     uint32_t words);
 126 static int qlt_dump_queue(qlt_state_t *qlt, caddr_t qadr, int entries,
 127     caddr_t buf, uint_t size_left);
 128 static int qlt_dump_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words,
 129     caddr_t buf, uint_t size_left);
 130 static int qlt_fwdump_dump_regs(qlt_state_t *qlt, caddr_t buf, int startaddr,
 131     int count, uint_t size_left);
 132 static int qlt_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 133     cred_t *credp, int *rval);
 134 static int qlt_open(dev_t *devp, int flag, int otype, cred_t *credp);
 135 static int qlt_close(dev_t dev, int flag, int otype, cred_t *credp);
 136 
 137 static int qlt_setup_msi(qlt_state_t *qlt);
 138 static int qlt_setup_msix(qlt_state_t *qlt);
 139 
 140 static int qlt_el_trace_desc_ctor(qlt_state_t *qlt);
 141 static int qlt_el_trace_desc_dtor(qlt_state_t *qlt);
 142 static int qlt_validate_trace_desc(qlt_state_t *qlt);
 143 static char *qlt_find_trace_start(qlt_state_t *qlt);
 144 
 145 static int qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval);
 146 static int qlt_read_string_prop(qlt_state_t *qlt, char *prop, char **prop_val);
 147 static int qlt_read_string_instance_prop(qlt_state_t *qlt, char *prop,
 148     char **prop_val);
 149 static int qlt_read_int_instance_prop(qlt_state_t *, char *, int);
 150 static int qlt_convert_string_to_ull(char *prop, int radix,
 151     u_longlong_t *result);
 152 static boolean_t qlt_wwn_overload_prop(qlt_state_t *qlt);
 153 static int qlt_quiesce(dev_info_t *dip);
 154 static fct_status_t qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t,
 155     uint32_t);
 156 static fct_status_t qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t,
 157     uint32_t *);
 158 static void qlt_mps_reset(qlt_state_t *qlt);
 159 static void qlt_properties(qlt_state_t *qlt);
 160 
 161 
 162 #define SETELSBIT(bmp, els)     (bmp)[((els) >> 3) & 0x1F] = \
 163         (uint8_t)((bmp)[((els) >> 3) & 0x1F] | ((uint8_t)1) << ((els) & 7))
 164 
 165 int qlt_enable_msix = 0;
 166 int qlt_enable_msi = 1;
 167 
 168 
 169 string_table_t prop_status_tbl[] = DDI_PROP_STATUS();
 170 
 171 /* Array to quickly calculate next free buf index to use */
 172 #if 0
 173 static int qlt_nfb[] = { 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 0xff };
 174 #endif
 175 
 176 static struct cb_ops qlt_cb_ops = {
 177         qlt_open,
 178         qlt_close,
 179         nodev,
 180         nodev,
 181         nodev,
 182         nodev,
 183         nodev,
 184         qlt_ioctl,
 185         nodev,
 186         nodev,
 187         nodev,
 188         nochpoll,
 189         ddi_prop_op,
 190         0,
 191         D_MP | D_NEW
 192 };
 193 
 194 static struct dev_ops qlt_ops = {
 195         DEVO_REV,
 196         0,
 197         nodev,
 198         nulldev,
 199         nulldev,
 200         qlt_attach,
 201         qlt_detach,
 202         nodev,
 203         &qlt_cb_ops,
 204         NULL,
 205         ddi_power,
 206         qlt_quiesce
 207 };
 208 
 209 #ifndef PORT_SPEED_10G
 210 #define PORT_SPEED_10G          16
 211 #endif
 212 
 213 static struct modldrv modldrv = {
 214         &mod_driverops,
 215         QLT_NAME" "QLT_VERSION,
 216         &qlt_ops,
 217 };
 218 
 219 static struct modlinkage modlinkage = {
 220         MODREV_1, &modldrv, NULL
 221 };
 222 
 223 void *qlt_state = NULL;
 224 kmutex_t qlt_global_lock;
 225 static uint32_t qlt_loaded_counter = 0;
 226 
 227 static char *pci_speeds[] = { " 33", "-X Mode 1 66", "-X Mode 1 100",
 228                         "-X Mode 1 133", "--Invalid--",
 229                         "-X Mode 2 66", "-X Mode 2 100",
 230                         "-X Mode 2 133", " 66" };
 231 
 232 /* Always use 64 bit DMA. */
 233 static ddi_dma_attr_t qlt_queue_dma_attr = {
 234         DMA_ATTR_V0,            /* dma_attr_version */
 235         0,                      /* low DMA address range */
 236         0xffffffffffffffff,     /* high DMA address range */
 237         0xffffffff,             /* DMA counter register */
 238         64,                     /* DMA address alignment */
 239         0xff,                   /* DMA burstsizes */
 240         1,                      /* min effective DMA size */
 241         0xffffffff,             /* max DMA xfer size */
 242         0xffffffff,             /* segment boundary */
 243         1,                      /* s/g list length */
 244         1,                      /* granularity of device */
 245         0                       /* DMA transfer flags */
 246 };
 247 
 248 /* qlogic logging */
 249 int enable_extended_logging = 0;
 250 
 251 static char qlt_provider_name[] = "qlt";
 252 static struct stmf_port_provider *qlt_pp;
 253 
 254 int
 255 _init(void)
 256 {
 257         int ret;
 258 
 259         ret = ddi_soft_state_init(&qlt_state, sizeof (qlt_state_t), 0);
 260         if (ret == 0) {
 261                 mutex_init(&qlt_global_lock, 0, MUTEX_DRIVER, 0);
 262                 qlt_pp = (stmf_port_provider_t *)stmf_alloc(
 263                     STMF_STRUCT_PORT_PROVIDER, 0, 0);
 264                 qlt_pp->pp_portif_rev = PORTIF_REV_1;
 265                 qlt_pp->pp_name = qlt_provider_name;
 266                 if (stmf_register_port_provider(qlt_pp) != STMF_SUCCESS) {
 267                         stmf_free(qlt_pp);
 268                         mutex_destroy(&qlt_global_lock);
 269                         ddi_soft_state_fini(&qlt_state);
 270                         return (EIO);
 271                 }
 272                 ret = mod_install(&modlinkage);
 273                 if (ret != 0) {
 274                         (void) stmf_deregister_port_provider(qlt_pp);
 275                         stmf_free(qlt_pp);
 276                         mutex_destroy(&qlt_global_lock);
 277                         ddi_soft_state_fini(&qlt_state);
 278                 }
 279         }
 280         return (ret);
 281 }
 282 
 283 int
 284 _fini(void)
 285 {
 286         int ret;
 287 
 288         if (qlt_loaded_counter)
 289                 return (EBUSY);
 290         ret = mod_remove(&modlinkage);
 291         if (ret == 0) {
 292                 (void) stmf_deregister_port_provider(qlt_pp);
 293                 stmf_free(qlt_pp);
 294                 mutex_destroy(&qlt_global_lock);
 295                 ddi_soft_state_fini(&qlt_state);
 296         }
 297         return (ret);
 298 }
 299 
 300 int
 301 _info(struct modinfo *modinfop)
 302 {
 303         return (mod_info(&modlinkage, modinfop));
 304 }
 305 
 306 
 307 static int
 308 qlt_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 309 {
 310         int             instance;
 311         qlt_state_t     *qlt;
 312         ddi_device_acc_attr_t   dev_acc_attr;
 313         uint16_t        did;
 314         uint16_t        val;
 315         uint16_t        mr;
 316         size_t          discard;
 317         uint_t          ncookies;
 318         int             max_read_size;
 319         int             max_payload_size;
 320         fct_status_t    ret;
 321 
 322         /* No support for suspend resume yet */
 323         if (cmd != DDI_ATTACH)
 324                 return (DDI_FAILURE);
 325         instance = ddi_get_instance(dip);
 326 
 327         if (ddi_soft_state_zalloc(qlt_state, instance) != DDI_SUCCESS) {
 328                 return (DDI_FAILURE);
 329         }
 330 
 331         if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) ==
 332             NULL) {
 333                 goto attach_fail_1;
 334         }
 335 
 336         qlt->instance = instance;
 337 
 338         qlt->nvram = (qlt_nvram_t *)kmem_zalloc(sizeof (qlt_nvram_t), KM_SLEEP);
 339         qlt->dip = dip;
 340 
 341         if (qlt_el_trace_desc_ctor(qlt) != DDI_SUCCESS) {
 342                 cmn_err(CE_WARN, "qlt(%d): can't setup el tracing", instance);
 343                 goto attach_fail_1;
 344         }
 345 
 346         EL(qlt, "instance=%d, ptr=%p\n", instance, (void *)qlt);
 347 
 348         if (pci_config_setup(dip, &qlt->pcicfg_acc_handle) != DDI_SUCCESS) {
 349                 goto attach_fail_2;
 350         }
 351         did = PCICFG_RD16(qlt, PCI_CONF_DEVID);
 352         if ((did != 0x2422) && (did != 0x2432) &&
 353             (did != 0x8432) && (did != 0x2532) &&
 354             (did != 0x8001)) {
 355                 cmn_err(CE_WARN, "qlt(%d): unknown devid(%x), failing attach",
 356                     instance, did);
 357                 goto attach_fail_4;
 358         }
 359 
 360         if ((did & 0xFF00) == 0x8000)
 361                 qlt->qlt_81xx_chip = 1;
 362         else if ((did & 0xFF00) == 0x2500)
 363                 qlt->qlt_25xx_chip = 1;
 364 
 365         dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
 366         dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
 367         dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
 368         if (ddi_regs_map_setup(dip, 2, &qlt->regs, 0, 0x100,
 369             &dev_acc_attr, &qlt->regs_acc_handle) != DDI_SUCCESS) {
 370                 goto attach_fail_4;
 371         }
 372         if (did == 0x2422) {
 373                 uint32_t pci_bits = REG_RD32(qlt, REG_CTRL_STATUS);
 374                 uint32_t slot = pci_bits & PCI_64_BIT_SLOT;
 375                 pci_bits >>= 8;
 376                 pci_bits &= 0xf;
 377                 if ((pci_bits == 3) || (pci_bits == 7)) {
 378                         cmn_err(CE_NOTE,
 379                             "!qlt(%d): HBA running at PCI%sMHz (%d)",
 380                             instance, pci_speeds[pci_bits], pci_bits);
 381                 } else {
 382                         cmn_err(CE_WARN,
 383                             "qlt(%d): HBA running at PCI%sMHz %s(%d)",
 384                             instance, (pci_bits <= 8) ? pci_speeds[pci_bits] :
 385                             "(Invalid)", ((pci_bits == 0) ||
 386                             (pci_bits == 8)) ? (slot ? "64 bit slot " :
 387                             "32 bit slot ") : "", pci_bits);
 388                 }
 389         }
 390         if ((ret = qlt_read_nvram(qlt)) != QLT_SUCCESS) {
 391                 cmn_err(CE_WARN, "qlt(%d): read nvram failure %llx", instance,
 392                     (unsigned long long)ret);
 393                 goto attach_fail_5;
 394         }
 395 
 396         qlt_properties(qlt);
 397 
 398         if (ddi_dma_alloc_handle(dip, &qlt_queue_dma_attr, DDI_DMA_SLEEP,
 399             0, &qlt->queue_mem_dma_handle) != DDI_SUCCESS) {
 400                 goto attach_fail_5;
 401         }
 402         if (ddi_dma_mem_alloc(qlt->queue_mem_dma_handle, TOTAL_DMA_MEM_SIZE,
 403             &dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
 404             &qlt->queue_mem_ptr, &discard, &qlt->queue_mem_acc_handle) !=
 405             DDI_SUCCESS) {
 406                 goto attach_fail_6;
 407         }
 408         if (ddi_dma_addr_bind_handle(qlt->queue_mem_dma_handle, NULL,
 409             qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE,
 410             DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
 411             &qlt->queue_mem_cookie, &ncookies) != DDI_SUCCESS) {
 412                 goto attach_fail_7;
 413         }
 414         if (ncookies != 1)
 415                 goto attach_fail_8;
 416         qlt->req_ptr = qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET;
 417         qlt->resp_ptr = qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET;
 418         qlt->preq_ptr = qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET;
 419         qlt->atio_ptr = qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET;
 420 
 421         /* mutex are inited in this function */
 422         if (qlt_setup_interrupts(qlt) != DDI_SUCCESS)
 423                 goto attach_fail_8;
 424 
 425         (void) snprintf(qlt->qlt_minor_name, sizeof (qlt->qlt_minor_name),
 426             "qlt%d", instance);
 427         (void) snprintf(qlt->qlt_port_alias, sizeof (qlt->qlt_port_alias),
 428             "%s,0", qlt->qlt_minor_name);
 429 
 430         if (ddi_create_minor_node(dip, qlt->qlt_minor_name, S_IFCHR,
 431             instance, DDI_NT_STMF_PP, 0) != DDI_SUCCESS) {
 432                 goto attach_fail_9;
 433         }
 434 
 435         cv_init(&qlt->rp_dereg_cv, NULL, CV_DRIVER, NULL);
 436         cv_init(&qlt->mbox_cv, NULL, CV_DRIVER, NULL);
 437         mutex_init(&qlt->qlt_ioctl_lock, NULL, MUTEX_DRIVER, NULL);
 438 
 439         /* Setup PCI cfg space registers */
 440         max_read_size = qlt_read_int_prop(qlt, "pci-max-read-request", 11);
 441         if (max_read_size == 11)
 442                 goto over_max_read_xfer_setting;
 443         if (did == 0x2422) {
 444                 if (max_read_size == 512)
 445                         val = 0;
 446                 else if (max_read_size == 1024)
 447                         val = 1;
 448                 else if (max_read_size == 2048)
 449                         val = 2;
 450                 else if (max_read_size == 4096)
 451                         val = 3;
 452                 else {
 453                         cmn_err(CE_WARN, "qlt(%d) malformed "
 454                             "pci-max-read-request in qlt.conf. Valid values "
 455                             "for this HBA are 512/1024/2048/4096", instance);
 456                         goto over_max_read_xfer_setting;
 457                 }
 458                 mr = (uint16_t)PCICFG_RD16(qlt, 0x4E);
 459                 mr = (uint16_t)(mr & 0xfff3);
 460                 mr = (uint16_t)(mr | (val << 2));
 461                 PCICFG_WR16(qlt, 0x4E, mr);
 462         } else if ((did == 0x2432) || (did == 0x8432) ||
 463             (did == 0x2532) || (did == 0x8001)) {
 464                 if (max_read_size == 128)
 465                         val = 0;
 466                 else if (max_read_size == 256)
 467                         val = 1;
 468                 else if (max_read_size == 512)
 469                         val = 2;
 470                 else if (max_read_size == 1024)
 471                         val = 3;
 472                 else if (max_read_size == 2048)
 473                         val = 4;
 474                 else if (max_read_size == 4096)
 475                         val = 5;
 476                 else {
 477                         cmn_err(CE_WARN, "qlt(%d) malformed "
 478                             "pci-max-read-request in qlt.conf. Valid values "
 479                             "for this HBA are 128/256/512/1024/2048/4096",
 480                             instance);
 481                         goto over_max_read_xfer_setting;
 482                 }
 483                 mr = (uint16_t)PCICFG_RD16(qlt, 0x54);
 484                 mr = (uint16_t)(mr & 0x8fff);
 485                 mr = (uint16_t)(mr | (val << 12));
 486                 PCICFG_WR16(qlt, 0x54, mr);
 487         } else {
 488                 cmn_err(CE_WARN, "qlt(%d): dont know how to set "
 489                     "pci-max-read-request for this device (%x)",
 490                     instance, did);
 491         }
 492 over_max_read_xfer_setting:;
 493 
 494         max_payload_size = qlt_read_int_prop(qlt, "pcie-max-payload-size", 11);
 495         if (max_payload_size == 11)
 496                 goto over_max_payload_setting;
 497         if ((did == 0x2432) || (did == 0x8432) ||
 498             (did == 0x2532) || (did == 0x8001)) {
 499                 if (max_payload_size == 128)
 500                         val = 0;
 501                 else if (max_payload_size == 256)
 502                         val = 1;
 503                 else if (max_payload_size == 512)
 504                         val = 2;
 505                 else if (max_payload_size == 1024)
 506                         val = 3;
 507                 else {
 508                         cmn_err(CE_WARN, "qlt(%d) malformed "
 509                             "pcie-max-payload-size in qlt.conf. Valid values "
 510                             "for this HBA are 128/256/512/1024",
 511                             instance);
 512                         goto over_max_payload_setting;
 513                 }
 514                 mr = (uint16_t)PCICFG_RD16(qlt, 0x54);
 515                 mr = (uint16_t)(mr & 0xff1f);
 516                 mr = (uint16_t)(mr | (val << 5));
 517                 PCICFG_WR16(qlt, 0x54, mr);
 518         } else {
 519                 cmn_err(CE_WARN, "qlt(%d): dont know how to set "
 520                     "pcie-max-payload-size for this device (%x)",
 521                     instance, did);
 522         }
 523 
 524 over_max_payload_setting:;
 525 
 526         qlt_enable_intr(qlt);
 527 
 528         if (qlt_port_start((caddr_t)qlt) != QLT_SUCCESS)
 529                 goto attach_fail_10;
 530 
 531         ddi_report_dev(dip);
 532         return (DDI_SUCCESS);
 533 
 534 attach_fail_10:;
 535         mutex_destroy(&qlt->qlt_ioctl_lock);
 536         cv_destroy(&qlt->mbox_cv);
 537         cv_destroy(&qlt->rp_dereg_cv);
 538         ddi_remove_minor_node(dip, qlt->qlt_minor_name);
 539 attach_fail_9:;
 540         qlt_destroy_mutex(qlt);
 541         qlt_release_intr(qlt);
 542 attach_fail_8:;
 543         (void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle);
 544 attach_fail_7:;
 545         ddi_dma_mem_free(&qlt->queue_mem_acc_handle);
 546 attach_fail_6:;
 547         ddi_dma_free_handle(&qlt->queue_mem_dma_handle);
 548 attach_fail_5:;
 549         ddi_regs_map_free(&qlt->regs_acc_handle);
 550 attach_fail_4:;
 551         pci_config_teardown(&qlt->pcicfg_acc_handle);
 552         kmem_free(qlt->nvram, sizeof (qlt_nvram_t));
 553         (void) qlt_el_trace_desc_dtor(qlt);
 554 attach_fail_2:;
 555 attach_fail_1:;
 556         ddi_soft_state_free(qlt_state, instance);
 557         return (DDI_FAILURE);
 558 }
 559 
 560 #define FCT_I_EVENT_BRING_PORT_OFFLINE  0x83
 561 
 562 /* ARGSUSED */
 563 static int
 564 qlt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 565 {
 566         qlt_state_t *qlt;
 567 
 568         int instance;
 569 
 570         instance = ddi_get_instance(dip);
 571         if ((qlt = (qlt_state_t *)ddi_get_soft_state(qlt_state, instance)) ==
 572             NULL) {
 573                 return (DDI_FAILURE);
 574         }
 575 
 576         if (qlt->fw_code01) {
 577                 return (DDI_FAILURE);
 578         }
 579 
 580         if ((qlt->qlt_state != FCT_STATE_OFFLINE) ||
 581             qlt->qlt_state_not_acked) {
 582                 return (DDI_FAILURE);
 583         }
 584         if (qlt_port_stop((caddr_t)qlt) != FCT_SUCCESS) {
 585                 return (DDI_FAILURE);
 586         }
 587 
 588         qlt_disable_intr(qlt);
 589 
 590         ddi_remove_minor_node(dip, qlt->qlt_minor_name);
 591         qlt_destroy_mutex(qlt);
 592         qlt_release_intr(qlt);
 593         (void) ddi_dma_unbind_handle(qlt->queue_mem_dma_handle);
 594         ddi_dma_mem_free(&qlt->queue_mem_acc_handle);
 595         ddi_dma_free_handle(&qlt->queue_mem_dma_handle);
 596         ddi_regs_map_free(&qlt->regs_acc_handle);
 597         pci_config_teardown(&qlt->pcicfg_acc_handle);
 598         kmem_free(qlt->nvram, sizeof (qlt_nvram_t));
 599         cv_destroy(&qlt->mbox_cv);
 600         cv_destroy(&qlt->rp_dereg_cv);
 601         (void) qlt_el_trace_desc_dtor(qlt);
 602         ddi_soft_state_free(qlt_state, instance);
 603 
 604         return (DDI_SUCCESS);
 605 }
 606 
 607 /*
 608  * qlt_quiesce  quiesce a device attached to the system.
 609  */
 610 static int
 611 qlt_quiesce(dev_info_t *dip)
 612 {
 613         qlt_state_t     *qlt;
 614         uint32_t        timer;
 615         uint32_t        stat;
 616 
 617         qlt = ddi_get_soft_state(qlt_state, ddi_get_instance(dip));
 618         if (qlt == NULL) {
 619                 /* Oh well.... */
 620                 return (DDI_SUCCESS);
 621         }
 622 
 623         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_HOST_TO_RISC_INTR));
 624         REG_WR16(qlt, REG_MBOX0, MBC_STOP_FIRMWARE);
 625         REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
 626         for (timer = 0; timer < 30000; timer++) {
 627                 stat = REG_RD32(qlt, REG_RISC_STATUS);
 628                 if (stat & RISC_HOST_INTR_REQUEST) {
 629                         if ((stat & FW_INTR_STATUS_MASK) < 0x12) {
 630                                 REG_WR32(qlt, REG_HCCR,
 631                                     HCCR_CMD(CLEAR_RISC_PAUSE));
 632                                 break;
 633                         }
 634                         REG_WR32(qlt, REG_HCCR,
 635                             HCCR_CMD(CLEAR_HOST_TO_RISC_INTR));
 636                 }
 637                 drv_usecwait(100);
 638         }
 639         /* Reset the chip. */
 640         REG_WR32(qlt, REG_CTRL_STATUS, CHIP_SOFT_RESET | DMA_SHUTDOWN_CTRL |
 641             PCI_X_XFER_CTRL);
 642         drv_usecwait(100);
 643 
 644         qlt_disable_intr(qlt);
 645 
 646         return (DDI_SUCCESS);
 647 }
 648 
 649 static void
 650 qlt_enable_intr(qlt_state_t *qlt)
 651 {
 652         if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
 653                 (void) ddi_intr_block_enable(qlt->htable, qlt->intr_cnt);
 654         } else {
 655                 int i;
 656                 for (i = 0; i < qlt->intr_cnt; i++)
 657                         (void) ddi_intr_enable(qlt->htable[i]);
 658         }
 659         qlt->qlt_intr_enabled = 1;
 660 }
 661 
 662 static void
 663 qlt_disable_intr(qlt_state_t *qlt)
 664 {
 665         if (qlt->intr_cap & DDI_INTR_FLAG_BLOCK) {
 666                 (void) ddi_intr_block_disable(qlt->htable, qlt->intr_cnt);
 667         } else {
 668                 int i;
 669                 for (i = 0; i < qlt->intr_cnt; i++)
 670                         (void) ddi_intr_disable(qlt->htable[i]);
 671         }
 672         qlt->qlt_intr_enabled = 0;
 673 }
 674 
 675 static void
 676 qlt_release_intr(qlt_state_t *qlt)
 677 {
 678         if (qlt->htable) {
 679                 int i;
 680                 for (i = 0; i < qlt->intr_cnt; i++) {
 681                         (void) ddi_intr_remove_handler(qlt->htable[i]);
 682                         (void) ddi_intr_free(qlt->htable[i]);
 683                 }
 684                 kmem_free(qlt->htable, (uint_t)qlt->intr_size);
 685         }
 686         qlt->htable = NULL;
 687         qlt->intr_pri = 0;
 688         qlt->intr_cnt = 0;
 689         qlt->intr_size = 0;
 690         qlt->intr_cap = 0;
 691 }
 692 
 693 
 694 static void
 695 qlt_init_mutex(qlt_state_t *qlt)
 696 {
 697         mutex_init(&qlt->req_lock, 0, MUTEX_DRIVER,
 698             INT2PTR(qlt->intr_pri, void *));
 699         mutex_init(&qlt->preq_lock, 0, MUTEX_DRIVER,
 700             INT2PTR(qlt->intr_pri, void *));
 701         mutex_init(&qlt->mbox_lock, NULL, MUTEX_DRIVER,
 702             INT2PTR(qlt->intr_pri, void *));
 703         mutex_init(&qlt->intr_lock, NULL, MUTEX_DRIVER,
 704             INT2PTR(qlt->intr_pri, void *));
 705 }
 706 
 707 static void
 708 qlt_destroy_mutex(qlt_state_t *qlt)
 709 {
 710         mutex_destroy(&qlt->req_lock);
 711         mutex_destroy(&qlt->preq_lock);
 712         mutex_destroy(&qlt->mbox_lock);
 713         mutex_destroy(&qlt->intr_lock);
 714 }
 715 
 716 
 717 static int
 718 qlt_setup_msix(qlt_state_t *qlt)
 719 {
 720         int count, avail, actual;
 721         int ret;
 722         int itype = DDI_INTR_TYPE_MSIX;
 723         int i;
 724 
 725         ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
 726         if (ret != DDI_SUCCESS || count == 0) {
 727                 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
 728                     count);
 729                 return (DDI_FAILURE);
 730         }
 731         ret = ddi_intr_get_navail(qlt->dip, itype, &avail);
 732         if (ret != DDI_SUCCESS || avail == 0) {
 733                 EL(qlt, "ddi_intr_get_navail status=%xh, avail=%d\n", ret,
 734                     avail);
 735                 return (DDI_FAILURE);
 736         }
 737         if (avail < count) {
 738                 stmf_trace(qlt->qlt_port_alias,
 739                     "qlt_setup_msix: nintrs=%d,avail=%d", count, avail);
 740         }
 741 
 742         qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t));
 743         qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
 744         ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
 745             DDI_INTR_ALLOC_NORMAL, count, &actual, 0);
 746         /* we need at least 2 interrupt vectors */
 747         if (ret != DDI_SUCCESS || actual < 2) {
 748                 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
 749                     actual);
 750                 ret = DDI_FAILURE;
 751                 goto release_intr;
 752         }
 753         if (actual < count) {
 754                 EL(qlt, "requested: %d, received: %d\n", count, actual);
 755         }
 756 
 757         qlt->intr_cnt = actual;
 758         ret =  ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri);
 759         if (ret != DDI_SUCCESS) {
 760                 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
 761                 ret = DDI_FAILURE;
 762                 goto release_intr;
 763         }
 764         qlt_init_mutex(qlt);
 765         for (i = 0; i < actual; i++) {
 766                 ret = ddi_intr_add_handler(qlt->htable[i], qlt_isr,
 767                     qlt, INT2PTR((uint_t)i, void *));
 768                 if (ret != DDI_SUCCESS) {
 769                         EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
 770                         goto release_mutex;
 771                 }
 772         }
 773 
 774         (void) ddi_intr_get_cap(qlt->htable[0], &qlt->intr_cap);
 775         qlt->intr_flags |= QLT_INTR_MSIX;
 776         return (DDI_SUCCESS);
 777 
 778 release_mutex:
 779         qlt_destroy_mutex(qlt);
 780 release_intr:
 781         for (i = 0; i < actual; i++)
 782                 (void) ddi_intr_free(qlt->htable[i]);
 783 #if 0
 784 free_mem:
 785 #endif
 786         kmem_free(qlt->htable, (uint_t)qlt->intr_size);
 787         qlt->htable = NULL;
 788         qlt_release_intr(qlt);
 789         return (ret);
 790 }
 791 
 792 
 793 static int
 794 qlt_setup_msi(qlt_state_t *qlt)
 795 {
 796         int count, avail, actual;
 797         int itype = DDI_INTR_TYPE_MSI;
 798         int ret;
 799         int i;
 800 
 801         /* get the # of interrupts */
 802         ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
 803         if (ret != DDI_SUCCESS || count == 0) {
 804                 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
 805                     count);
 806                 return (DDI_FAILURE);
 807         }
 808         ret = ddi_intr_get_navail(qlt->dip, itype, &avail);
 809         if (ret != DDI_SUCCESS || avail == 0) {
 810                 EL(qlt, "ddi_intr_get_navail status=%xh, avail=%d\n", ret,
 811                     avail);
 812                 return (DDI_FAILURE);
 813         }
 814         if (avail < count) {
 815                 EL(qlt, "nintrs=%d, avail=%d\n", count, avail);
 816         }
 817         /* MSI requires only 1 interrupt. */
 818         count = 1;
 819 
 820         /* allocate interrupt */
 821         qlt->intr_size = (int)(count * (int)sizeof (ddi_intr_handle_t));
 822         qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
 823         ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
 824             0, count, &actual, DDI_INTR_ALLOC_NORMAL);
 825         if (ret != DDI_SUCCESS || actual == 0) {
 826                 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
 827                     actual);
 828                 ret = DDI_FAILURE;
 829                 goto free_mem;
 830         }
 831         if (actual < count) {
 832                 EL(qlt, "requested: %d, received: %d\n", count, actual);
 833         }
 834         qlt->intr_cnt = actual;
 835 
 836         /*
 837          * Get priority for first msi, assume remaining are all the same.
 838          */
 839         ret =  ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri);
 840         if (ret != DDI_SUCCESS) {
 841                 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
 842                 ret = DDI_FAILURE;
 843                 goto release_intr;
 844         }
 845         qlt_init_mutex(qlt);
 846 
 847         /* add handler */
 848         for (i = 0; i < actual; i++) {
 849                 ret = ddi_intr_add_handler(qlt->htable[i], qlt_isr,
 850                     qlt, INT2PTR((uint_t)i, void *));
 851                 if (ret != DDI_SUCCESS) {
 852                         EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
 853                         goto release_mutex;
 854                 }
 855         }
 856 
 857         (void) ddi_intr_get_cap(qlt->htable[0], &qlt->intr_cap);
 858         qlt->intr_flags |= QLT_INTR_MSI;
 859         return (DDI_SUCCESS);
 860 
 861 release_mutex:
 862         qlt_destroy_mutex(qlt);
 863 release_intr:
 864         for (i = 0; i < actual; i++)
 865                 (void) ddi_intr_free(qlt->htable[i]);
 866 free_mem:
 867         kmem_free(qlt->htable, (uint_t)qlt->intr_size);
 868         qlt->htable = NULL;
 869         qlt_release_intr(qlt);
 870         return (ret);
 871 }
 872 
 873 static int
 874 qlt_setup_fixed(qlt_state_t *qlt)
 875 {
 876         int count;
 877         int actual;
 878         int ret;
 879         int itype = DDI_INTR_TYPE_FIXED;
 880 
 881         ret = ddi_intr_get_nintrs(qlt->dip, itype, &count);
 882         /* Fixed interrupts can only have one interrupt. */
 883         if (ret != DDI_SUCCESS || count != 1) {
 884                 EL(qlt, "ddi_intr_get_nintrs status=%xh, count=%d\n", ret,
 885                     count);
 886                 return (DDI_FAILURE);
 887         }
 888 
 889         qlt->intr_size = sizeof (ddi_intr_handle_t);
 890         qlt->htable = kmem_zalloc((uint_t)qlt->intr_size, KM_SLEEP);
 891         ret = ddi_intr_alloc(qlt->dip, qlt->htable, itype,
 892             DDI_INTR_ALLOC_NORMAL, count, &actual, 0);
 893         if (ret != DDI_SUCCESS || actual != 1) {
 894                 EL(qlt, "ddi_intr_alloc status=%xh, actual=%d\n", ret,
 895                     actual);
 896                 ret = DDI_FAILURE;
 897                 goto free_mem;
 898         }
 899 
 900         qlt->intr_cnt = actual;
 901         ret =  ddi_intr_get_pri(qlt->htable[0], &qlt->intr_pri);
 902         if (ret != DDI_SUCCESS) {
 903                 EL(qlt, "ddi_intr_get_pri status=%xh\n", ret);
 904                 ret = DDI_FAILURE;
 905                 goto release_intr;
 906         }
 907         qlt_init_mutex(qlt);
 908         ret = ddi_intr_add_handler(qlt->htable[0], qlt_isr, qlt, 0);
 909         if (ret != DDI_SUCCESS) {
 910                 EL(qlt, "ddi_intr_add_handler status=%xh\n", ret);
 911                 goto release_mutex;
 912         }
 913 
 914         qlt->intr_flags |= QLT_INTR_FIXED;
 915         return (DDI_SUCCESS);
 916 
 917 release_mutex:
 918         qlt_destroy_mutex(qlt);
 919 release_intr:
 920         (void) ddi_intr_free(qlt->htable[0]);
 921 free_mem:
 922         kmem_free(qlt->htable, (uint_t)qlt->intr_size);
 923         qlt->htable = NULL;
 924         qlt_release_intr(qlt);
 925         return (ret);
 926 }
 927 
 928 static int
 929 qlt_setup_interrupts(qlt_state_t *qlt)
 930 {
 931         int itypes = 0;
 932 
 933 /*
 934  * x86 has a bug in the ddi_intr_block_enable/disable area (6562198).
 935  */
 936 #ifndef __sparc
 937         if (qlt_enable_msi != 0) {
 938 #endif
 939         if (ddi_intr_get_supported_types(qlt->dip, &itypes) != DDI_SUCCESS) {
 940                 itypes = DDI_INTR_TYPE_FIXED;
 941         }
 942 
 943         if (qlt_enable_msix && (itypes & DDI_INTR_TYPE_MSIX)) {
 944                 if (qlt_setup_msix(qlt) == DDI_SUCCESS)
 945                         return (DDI_SUCCESS);
 946         }
 947 
 948         if (itypes & DDI_INTR_TYPE_MSI) {
 949                 if (qlt_setup_msi(qlt) == DDI_SUCCESS)
 950                         return (DDI_SUCCESS);
 951         }
 952 #ifndef __sparc
 953         }
 954 #endif
 955         return (qlt_setup_fixed(qlt));
 956 }
 957 
 958 /*
 959  * Filling the hba attributes
 960  */
 961 void
 962 qlt_populate_hba_fru_details(struct fct_local_port *port,
 963     struct fct_port_attrs *port_attrs)
 964 {
 965         caddr_t bufp;
 966         int len;
 967         qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
 968 
 969         (void) snprintf(port_attrs->manufacturer, FCHBA_MANUFACTURER_LEN,
 970             "QLogic Corp.");
 971         (void) snprintf(port_attrs->driver_name, FCHBA_DRIVER_NAME_LEN,
 972             "%s", QLT_NAME);
 973         (void) snprintf(port_attrs->driver_version, FCHBA_DRIVER_VERSION_LEN,
 974             "%s", QLT_VERSION);
 975         port_attrs->serial_number[0] = '\0';
 976         port_attrs->hardware_version[0] = '\0';
 977 
 978         (void) snprintf(port_attrs->firmware_version,
 979             FCHBA_FIRMWARE_VERSION_LEN, "%d.%d.%d", qlt->fw_major,
 980             qlt->fw_minor, qlt->fw_subminor);
 981 
 982         /* Get FCode version */
 983         if (ddi_getlongprop(DDI_DEV_T_ANY, qlt->dip, PROP_LEN_AND_VAL_ALLOC |
 984             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "version", (caddr_t)&bufp,
 985             (int *)&len) == DDI_PROP_SUCCESS) {
 986                 (void) snprintf(port_attrs->option_rom_version,
 987                     FCHBA_OPTION_ROM_VERSION_LEN, "%s", bufp);
 988                 kmem_free(bufp, (uint_t)len);
 989                 bufp = NULL;
 990         } else {
 991 #ifdef __sparc
 992                 (void) snprintf(port_attrs->option_rom_version,
 993                     FCHBA_OPTION_ROM_VERSION_LEN, "No Fcode found");
 994 #else
 995                 (void) snprintf(port_attrs->option_rom_version,
 996                     FCHBA_OPTION_ROM_VERSION_LEN, "N/A");
 997 #endif
 998         }
 999         port_attrs->vendor_specific_id = qlt->nvram->subsystem_vendor_id[0] |
1000             qlt->nvram->subsystem_vendor_id[1] << 8;
1001 
1002         port_attrs->max_frame_size = qlt->nvram->max_frame_length[1] << 8 |
1003             qlt->nvram->max_frame_length[0];
1004 
1005         port_attrs->supported_cos = 0x10000000;
1006         port_attrs->supported_speed = PORT_SPEED_1G |
1007             PORT_SPEED_2G | PORT_SPEED_4G;
1008         if (qlt->qlt_25xx_chip)
1009                 port_attrs->supported_speed = PORT_SPEED_2G | PORT_SPEED_4G |
1010                     PORT_SPEED_8G;
1011         if (qlt->qlt_81xx_chip)
1012                 port_attrs->supported_speed = PORT_SPEED_10G;
1013 
1014         /* limit string length to nvr model_name length */
1015         len = (qlt->qlt_81xx_chip) ? 16 : 8;
1016         (void) snprintf(port_attrs->model,
1017             (uint_t)(len < FCHBA_MODEL_LEN ? len : FCHBA_MODEL_LEN),
1018             "%s", qlt->nvram->model_name);
1019 
1020         (void) snprintf(port_attrs->model_description,
1021             (uint_t)(len < FCHBA_MODEL_DESCRIPTION_LEN ? len :
1022             FCHBA_MODEL_DESCRIPTION_LEN),
1023             "%s", qlt->nvram->model_name);
1024 }
1025 
1026 /* ARGSUSED */
1027 fct_status_t
1028 qlt_info(uint32_t cmd, fct_local_port_t *port,
1029     void *arg, uint8_t *buf, uint32_t *bufsizep)
1030 {
1031         qlt_state_t     *qlt = (qlt_state_t *)port->port_fca_private;
1032         mbox_cmd_t      *mcp;
1033         fct_status_t    ret = FCT_SUCCESS;
1034         uint8_t         *p;
1035         fct_port_link_status_t  *link_status;
1036 
1037         switch (cmd) {
1038         case FC_TGT_PORT_RLS:
1039                 if ((*bufsizep) < sizeof (fct_port_link_status_t)) {
1040                         EL(qlt, "FC_TGT_PORT_RLS bufsizep=%xh < "
1041                             "fct_port_link_status_t=%xh\n", *bufsizep,
1042                             sizeof (fct_port_link_status_t));
1043                         ret = FCT_FAILURE;
1044                         break;
1045                 }
1046                 /* send mailbox command to get link status */
1047                 mcp = qlt_alloc_mailbox_command(qlt, 156);
1048                 if (mcp == NULL) {
1049                         EL(qlt, "qlt_alloc_mailbox_command mcp=null\n");
1050                         ret = FCT_ALLOC_FAILURE;
1051                         break;
1052                 }
1053 
1054                 /* GET LINK STATUS count */
1055                 mcp->to_fw[0] = MBC_GET_STATUS_COUNTS;
1056                 mcp->to_fw[8] = 156/4;
1057                 mcp->to_fw_mask |= BIT_1 | BIT_8;
1058                 mcp->from_fw_mask |= BIT_1 | BIT_2;
1059 
1060                 ret = qlt_mailbox_command(qlt, mcp);
1061                 if (ret != QLT_SUCCESS) {
1062                         EL(qlt, "qlt_mailbox_command=6dh status=%llxh\n", ret);
1063                         qlt_free_mailbox_command(qlt, mcp);
1064                         break;
1065                 }
1066                 qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
1067 
1068                 p = mcp->dbuf->db_sglist[0].seg_addr;
1069                 link_status = (fct_port_link_status_t *)buf;
1070                 link_status->LinkFailureCount = LE_32(*((uint32_t *)p));
1071                 link_status->LossOfSyncCount = LE_32(*((uint32_t *)(p + 4)));
1072                 link_status->LossOfSignalsCount = LE_32(*((uint32_t *)(p + 8)));
1073                 link_status->PrimitiveSeqProtocolErrorCount =
1074                     LE_32(*((uint32_t *)(p + 12)));
1075                 link_status->InvalidTransmissionWordCount =
1076                     LE_32(*((uint32_t *)(p + 16)));
1077                 link_status->InvalidCRCCount =
1078                     LE_32(*((uint32_t *)(p + 20)));
1079 
1080                 qlt_free_mailbox_command(qlt, mcp);
1081                 break;
1082         default:
1083                 EL(qlt, "Unknown cmd=%xh\n", cmd);
1084                 ret = FCT_FAILURE;
1085                 break;
1086         }
1087         return (ret);
1088 }
1089 
1090 fct_status_t
1091 qlt_port_start(caddr_t arg)
1092 {
1093         qlt_state_t *qlt = (qlt_state_t *)arg;
1094         fct_local_port_t *port;
1095         fct_dbuf_store_t *fds;
1096         fct_status_t ret;
1097 
1098         if (qlt_dmem_init(qlt) != QLT_SUCCESS) {
1099                 return (FCT_FAILURE);
1100         }
1101         /* Initialize the ddi_dma_handle free pool */
1102         qlt_dma_handle_pool_init(qlt);
1103 
1104         port = (fct_local_port_t *)fct_alloc(FCT_STRUCT_LOCAL_PORT, 0, 0);
1105         if (port == NULL) {
1106                 goto qlt_pstart_fail_1;
1107         }
1108         fds = (fct_dbuf_store_t *)fct_alloc(FCT_STRUCT_DBUF_STORE, 0, 0);
1109         if (fds == NULL) {
1110                 goto qlt_pstart_fail_2;
1111         }
1112         qlt->qlt_port = port;
1113         fds->fds_alloc_data_buf = qlt_dmem_alloc;
1114         fds->fds_free_data_buf = qlt_dmem_free;
1115         fds->fds_setup_dbuf = qlt_dma_setup_dbuf;
1116         fds->fds_teardown_dbuf = qlt_dma_teardown_dbuf;
1117         fds->fds_max_sgl_xfer_len = QLT_DMA_SG_LIST_LENGTH * MMU_PAGESIZE;
1118         fds->fds_copy_threshold = MMU_PAGESIZE;
1119         fds->fds_fca_private = (void *)qlt;
1120         /*
1121          * Since we keep everything in the state struct and dont allocate any
1122          * port private area, just use that pointer to point to the
1123          * state struct.
1124          */
1125         port->port_fca_private = qlt;
1126         port->port_fca_abort_timeout = 5 * 1000;     /* 5 seconds */
1127         bcopy(qlt->nvram->node_name, port->port_nwwn, 8);
1128         bcopy(qlt->nvram->port_name, port->port_pwwn, 8);
1129         fct_wwn_to_str(port->port_nwwn_str, port->port_nwwn);
1130         fct_wwn_to_str(port->port_pwwn_str, port->port_pwwn);
1131         port->port_default_alias = qlt->qlt_port_alias;
1132         port->port_pp = qlt_pp;
1133         port->port_fds = fds;
1134         port->port_max_logins = QLT_MAX_LOGINS;
1135         port->port_max_xchges = QLT_MAX_XCHGES;
1136         port->port_fca_fcp_cmd_size = sizeof (qlt_cmd_t);
1137         port->port_fca_rp_private_size = sizeof (qlt_remote_port_t);
1138         port->port_fca_sol_els_private_size = sizeof (qlt_cmd_t);
1139         port->port_fca_sol_ct_private_size = sizeof (qlt_cmd_t);
1140         port->port_get_link_info = qlt_get_link_info;
1141         port->port_register_remote_port = qlt_register_remote_port;
1142         port->port_deregister_remote_port = qlt_deregister_remote_port;
1143         port->port_send_cmd = qlt_send_cmd;
1144         port->port_xfer_scsi_data = qlt_xfer_scsi_data;
1145         port->port_send_cmd_response = qlt_send_cmd_response;
1146         port->port_abort_cmd = qlt_abort_cmd;
1147         port->port_ctl = qlt_ctl;
1148         port->port_flogi_xchg = qlt_do_flogi;
1149         port->port_populate_hba_details = qlt_populate_hba_fru_details;
1150         port->port_info = qlt_info;
1151         port->port_fca_version = FCT_FCA_MODREV_1;
1152 
1153         if ((ret = fct_register_local_port(port)) != FCT_SUCCESS) {
1154                 EL(qlt, "fct_register_local_port status=%llxh\n", ret);
1155                 goto qlt_pstart_fail_2_5;
1156         }
1157 
1158         return (QLT_SUCCESS);
1159 #if 0
1160 qlt_pstart_fail_3:
1161         (void) fct_deregister_local_port(port);
1162 #endif
1163 qlt_pstart_fail_2_5:
1164         fct_free(fds);
1165 qlt_pstart_fail_2:
1166         fct_free(port);
1167         qlt->qlt_port = NULL;
1168 qlt_pstart_fail_1:
1169         qlt_dma_handle_pool_fini(qlt);
1170         qlt_dmem_fini(qlt);
1171         return (QLT_FAILURE);
1172 }
1173 
1174 fct_status_t
1175 qlt_port_stop(caddr_t arg)
1176 {
1177         qlt_state_t *qlt = (qlt_state_t *)arg;
1178         fct_status_t ret;
1179 
1180         if ((ret = fct_deregister_local_port(qlt->qlt_port)) != FCT_SUCCESS) {
1181                 EL(qlt, "fct_register_local_port status=%llxh\n", ret);
1182                 return (QLT_FAILURE);
1183         }
1184         fct_free(qlt->qlt_port->port_fds);
1185         fct_free(qlt->qlt_port);
1186         qlt->qlt_port = NULL;
1187         qlt_dma_handle_pool_fini(qlt);
1188         qlt_dmem_fini(qlt);
1189         return (QLT_SUCCESS);
1190 }
1191 
1192 /*
1193  * Called by framework to init the HBA.
1194  * Can be called in the middle of I/O. (Why ??)
1195  * Should make sure sane state both before and after the initialization
1196  */
1197 fct_status_t
1198 qlt_port_online(qlt_state_t *qlt)
1199 {
1200         uint64_t        da;
1201         int             instance, i;
1202         fct_status_t    ret;
1203         uint16_t        rcount;
1204         caddr_t         icb;
1205         mbox_cmd_t      *mcp;
1206         uint8_t         *elsbmp;
1207 
1208         instance = ddi_get_instance(qlt->dip);
1209 
1210         /* XXX Make sure a sane state */
1211 
1212         if ((ret = qlt_download_fw(qlt)) != QLT_SUCCESS) {
1213                 cmn_err(CE_NOTE, "reset chip failed %llx", (long long)ret);
1214                 return (ret);
1215         }
1216 
1217         bzero(qlt->queue_mem_ptr, TOTAL_DMA_MEM_SIZE);
1218 
1219         /* Get resource count */
1220         REG_WR16(qlt, REG_MBOX(0), MBC_GET_RESOURCE_COUNTS);
1221         ret = qlt_raw_mailbox_command(qlt);
1222         rcount = REG_RD16(qlt, REG_MBOX(3));
1223         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
1224         if (ret != QLT_SUCCESS) {
1225                 EL(qlt, "qlt_raw_mailbox_command=42h status=%llxh\n", ret);
1226                 return (ret);
1227         }
1228 
1229         /* Enable PUREX */
1230         REG_WR16(qlt, REG_MBOX(0), MBC_SET_ADDITIONAL_FIRMWARE_OPT);
1231         REG_WR16(qlt, REG_MBOX(1), OPT_PUREX_ENABLE);
1232         REG_WR16(qlt, REG_MBOX(2), 0x0);
1233         REG_WR16(qlt, REG_MBOX(3), 0x0);
1234         ret = qlt_raw_mailbox_command(qlt);
1235         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
1236         if (ret != QLT_SUCCESS) {
1237                 EL(qlt, "qlt_raw_mailbox_command=38h status=%llxh\n", ret);
1238                 cmn_err(CE_NOTE, "Enable PUREX failed");
1239                 return (ret);
1240         }
1241 
1242         /* Pass ELS bitmap to fw */
1243         REG_WR16(qlt, REG_MBOX(0), MBC_SET_PARAMETERS);
1244         REG_WR16(qlt, REG_MBOX(1), PARAM_TYPE(PUREX_ELS_CMDS));
1245         elsbmp = (uint8_t *)qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET;
1246         bzero(elsbmp, 32);
1247         da = qlt->queue_mem_cookie.dmac_laddress;
1248         da += MBOX_DMA_MEM_OFFSET;
1249         REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
1250         REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
1251         REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
1252         REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
1253         SETELSBIT(elsbmp, ELS_OP_PLOGI);
1254         SETELSBIT(elsbmp, ELS_OP_LOGO);
1255         SETELSBIT(elsbmp, ELS_OP_ABTX);
1256         SETELSBIT(elsbmp, ELS_OP_ECHO);
1257         SETELSBIT(elsbmp, ELS_OP_PRLI);
1258         SETELSBIT(elsbmp, ELS_OP_PRLO);
1259         SETELSBIT(elsbmp, ELS_OP_SCN);
1260         SETELSBIT(elsbmp, ELS_OP_TPRLO);
1261         SETELSBIT(elsbmp, ELS_OP_PDISC);
1262         SETELSBIT(elsbmp, ELS_OP_ADISC);
1263         SETELSBIT(elsbmp, ELS_OP_RSCN);
1264         SETELSBIT(elsbmp, ELS_OP_RNID);
1265         (void) ddi_dma_sync(qlt->queue_mem_dma_handle, MBOX_DMA_MEM_OFFSET, 32,
1266             DDI_DMA_SYNC_FORDEV);
1267         ret = qlt_raw_mailbox_command(qlt);
1268         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
1269         if (ret != QLT_SUCCESS) {
1270                 EL(qlt, "qlt_raw_mailbox_command=59h status=llxh\n", ret);
1271                 cmn_err(CE_NOTE, "Set ELS Bitmap failed ret=%llx, "
1272                     "elsbmp0=%x elabmp1=%x", (long long)ret, elsbmp[0],
1273                     elsbmp[1]);
1274                 return (ret);
1275         }
1276 
1277         /* Init queue pointers */
1278         REG_WR32(qlt, REG_REQ_IN_PTR, 0);
1279         REG_WR32(qlt, REG_REQ_OUT_PTR, 0);
1280         REG_WR32(qlt, REG_RESP_IN_PTR, 0);
1281         REG_WR32(qlt, REG_RESP_OUT_PTR, 0);
1282         REG_WR32(qlt, REG_PREQ_IN_PTR, 0);
1283         REG_WR32(qlt, REG_PREQ_OUT_PTR, 0);
1284         REG_WR32(qlt, REG_ATIO_IN_PTR, 0);
1285         REG_WR32(qlt, REG_ATIO_OUT_PTR, 0);
1286         qlt->req_ndx_to_fw = qlt->req_ndx_from_fw = 0;
1287         qlt->req_available = REQUEST_QUEUE_ENTRIES - 1;
1288         qlt->resp_ndx_to_fw = qlt->resp_ndx_from_fw = 0;
1289         qlt->preq_ndx_to_fw = qlt->preq_ndx_from_fw = 0;
1290         qlt->atio_ndx_to_fw = qlt->atio_ndx_from_fw = 0;
1291 
1292         /*
1293          * XXX support for tunables. Also should we cache icb ?
1294          */
1295         if (qlt->qlt_81xx_chip) {
1296             /* allocate extra 64 bytes for Extended init control block */
1297                 mcp = qlt_alloc_mailbox_command(qlt, 0xC0);
1298         } else {
1299                 mcp = qlt_alloc_mailbox_command(qlt, 0x80);
1300         }
1301         if (mcp == NULL) {
1302                 EL(qlt, "qlt_alloc_mailbox_command mcp=null\n");
1303                 return (STMF_ALLOC_FAILURE);
1304         }
1305         icb = (caddr_t)mcp->dbuf->db_sglist[0].seg_addr;
1306         if (qlt->qlt_81xx_chip) {
1307                 bzero(icb, 0xC0);
1308         } else {
1309                 bzero(icb, 0x80);
1310         }
1311         da = qlt->queue_mem_cookie.dmac_laddress;
1312         DMEM_WR16(qlt, icb, 1);         /* Version */
1313         DMEM_WR16(qlt, icb+4, 2112);    /* Max frame length */
1314         DMEM_WR16(qlt, icb+6, 16);      /* Execution throttle */
1315         DMEM_WR16(qlt, icb+8, rcount);  /* Xchg count */
1316         DMEM_WR16(qlt, icb+0x0a, 0x00); /* Hard address (not used) */
1317         bcopy(qlt->qlt_port->port_pwwn, icb+0x0c, 8);
1318         bcopy(qlt->qlt_port->port_nwwn, icb+0x14, 8);
1319         DMEM_WR16(qlt, icb+0x20, 3);    /* Login retry count */
1320         DMEM_WR16(qlt, icb+0x24, RESPONSE_QUEUE_ENTRIES);
1321         DMEM_WR16(qlt, icb+0x26, REQUEST_QUEUE_ENTRIES);
1322         if (!qlt->qlt_81xx_chip) {
1323                 DMEM_WR16(qlt, icb+0x28, 100); /* ms of NOS/OLS for Link down */
1324         }
1325         DMEM_WR16(qlt, icb+0x2a, PRIORITY_QUEUE_ENTRIES);
1326         DMEM_WR64(qlt, icb+0x2c, (da+REQUEST_QUEUE_OFFSET));
1327         DMEM_WR64(qlt, icb+0x34, (da+RESPONSE_QUEUE_OFFSET));
1328         DMEM_WR64(qlt, icb+0x3c, (da+PRIORITY_QUEUE_OFFSET));
1329         DMEM_WR16(qlt, icb+0x4e, ATIO_QUEUE_ENTRIES);
1330         DMEM_WR64(qlt, icb+0x50, (da+ATIO_QUEUE_OFFSET));
1331         DMEM_WR16(qlt, icb+0x58, 2);    /* Interrupt delay Timer */
1332         DMEM_WR16(qlt, icb+0x5a, 4);    /* Login timeout (secs) */
1333         if (qlt->qlt_81xx_chip) {
1334                 qlt_nvram_81xx_t *qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
1335 
1336                 DMEM_WR32(qlt, icb+0x5c, BIT_5 | BIT_4); /* fw options 1 */
1337                 DMEM_WR32(qlt, icb+0x64, BIT_20 | BIT_4); /* fw options 3 */
1338                 DMEM_WR32(qlt, icb+0x70,
1339                     qlt81nvr->enode_mac[0] |
1340                     (qlt81nvr->enode_mac[1] << 8) |
1341                     (qlt81nvr->enode_mac[2] << 16) |
1342                     (qlt81nvr->enode_mac[3] << 24));
1343                 DMEM_WR16(qlt, icb+0x74,
1344                     qlt81nvr->enode_mac[4] |
1345                     (qlt81nvr->enode_mac[5] << 8));
1346                 } else {
1347                         DMEM_WR32(qlt, icb+0x5c, BIT_11 | BIT_5 | BIT_4 |
1348                             BIT_2 | BIT_1 | BIT_0);
1349                         DMEM_WR32(qlt, icb+0x60, BIT_5);
1350                         DMEM_WR32(qlt, icb+0x64, BIT_14 | BIT_8 | BIT_7 |
1351                             BIT_4);
1352                 }
1353 
1354         if (qlt->qlt_81xx_chip) {
1355                 qlt_dmem_bctl_t         *bctl;
1356                 uint32_t                index;
1357                 caddr_t                 src;
1358                 caddr_t                 dst;
1359                 qlt_nvram_81xx_t        *qlt81nvr;
1360 
1361                 dst = icb+0x80;
1362                 qlt81nvr = (qlt_nvram_81xx_t *)qlt->nvram;
1363                 src = (caddr_t)&qlt81nvr->ext_blk;
1364                 index = sizeof (qlt_ext_icb_81xx_t);
1365 
1366                 /* Use defaults for cases where we find nothing in NVR */
1367                 if (*src == 0) {
1368                         EL(qlt, "nvram eicb=null\n");
1369                         cmn_err(CE_NOTE, "qlt(%d) NVR eicb is zeroed",
1370                             instance);
1371                         qlt81nvr->ext_blk.version[0] = 1;
1372 /*
1373  * not yet, for !FIP firmware at least
1374  *
1375  *                qlt81nvr->ext_blk.fcf_vlan_match = 0x81;
1376  */
1377 #ifdef _LITTLE_ENDIAN
1378                         qlt81nvr->ext_blk.fcf_vlan_id[0] = 0xEA;
1379                         qlt81nvr->ext_blk.fcf_vlan_id[1] = 0x03;
1380 #else
1381                         qlt81nvr->ext_blk.fcf_vlan_id[1] = 0xEA;
1382                         qlt81nvr->ext_blk.fcf_vlan_id[0] = 0x03;
1383 #endif
1384                 }
1385 
1386                 while (index--) {
1387                         *dst++ = *src++;
1388                 }
1389 
1390                 bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private;
1391                 da = bctl->bctl_dev_addr + 0x80; /* base addr of eicb (phys) */
1392 
1393                 mcp->to_fw[11] = LSW(LSD(da));
1394                 mcp->to_fw[10] = MSW(LSD(da));
1395                 mcp->to_fw[13] = LSW(MSD(da));
1396                 mcp->to_fw[12] = MSW(MSD(da));
1397                 mcp->to_fw[14] = (uint16_t)(sizeof (qlt_ext_icb_81xx_t) &
1398                     0xffff);
1399 
1400                 /* eicb enable */
1401                 mcp->to_fw[1] = (uint16_t)(mcp->to_fw[1] | BIT_0);
1402                 mcp->to_fw_mask |= BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 |
1403                     BIT_1;
1404         }
1405 
1406         qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORDEV);
1407         mcp->to_fw[0] = MBC_INITIALIZE_FIRMWARE;
1408 
1409         /*
1410          * This is the 1st command after adapter initialize which will
1411          * use interrupts and regular mailbox interface.
1412          */
1413         qlt->mbox_io_state = MBOX_STATE_READY;
1414         REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
1415         /* Issue mailbox to firmware */
1416         ret = qlt_mailbox_command(qlt, mcp);
1417         if (ret != QLT_SUCCESS) {
1418                 EL(qlt, "qlt_mailbox_command=60h status=%llxh\n", ret);
1419                 cmn_err(CE_NOTE, "qlt(%d) init fw failed %llx, intr status %x",
1420                     instance, (long long)ret, REG_RD32(qlt, REG_INTR_STATUS));
1421         }
1422 
1423         mcp->to_fw_mask = BIT_0;
1424         mcp->from_fw_mask = BIT_0 | BIT_1;
1425         mcp->to_fw[0] = 0x28;
1426         ret = qlt_mailbox_command(qlt, mcp);
1427         if (ret != QLT_SUCCESS) {
1428                 EL(qlt, "qlt_mailbox_command=28h status=%llxh\n", ret);
1429                 cmn_err(CE_NOTE, "qlt(%d) get_fw_options %llx", instance,
1430                     (long long)ret);
1431         }
1432 
1433         /*
1434          * Report FW versions for 81xx - MPI rev is useful
1435          */
1436         if (qlt->qlt_81xx_chip) {
1437                 mcp->to_fw_mask = BIT_0;
1438                 mcp->from_fw_mask = BIT_11 | BIT_10 | BIT_3 | BIT_2 | BIT_1 |
1439                     BIT_0;
1440                 mcp->to_fw[0] = 0x8;
1441                 ret = qlt_mailbox_command(qlt, mcp);
1442                 if (ret != QLT_SUCCESS) {
1443                         EL(qlt, "about fw failed: %llx\n", (long long)ret);
1444                 } else {
1445                         EL(qlt, "Firmware version %d.%d.%d, MPI: %d.%d.%d\n",
1446                             mcp->from_fw[1], mcp->from_fw[2], mcp->from_fw[3],
1447                             mcp->from_fw[10] & 0xff, mcp->from_fw[11] >> 8,
1448                             mcp->from_fw[11] & 0xff);
1449                 }
1450         }
1451 
1452         qlt_free_mailbox_command(qlt, mcp);
1453 
1454         for (i = 0; i < 5; i++) {
1455                 qlt->qlt_bufref[i] = 0;
1456         }
1457         qlt->qlt_bumpbucket = 0;
1458         qlt->qlt_pmintry = 0;
1459         qlt->qlt_pmin_ok = 0;
1460 
1461         if (ret != QLT_SUCCESS)
1462                 return (ret);
1463         return (FCT_SUCCESS);
1464 }
1465 
1466 fct_status_t
1467 qlt_port_offline(qlt_state_t *qlt)
1468 {
1469         int             retries;
1470 
1471         mutex_enter(&qlt->mbox_lock);
1472 
1473         if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) {
1474                 mutex_exit(&qlt->mbox_lock);
1475                 goto poff_mbox_done;
1476         }
1477 
1478         /* Wait to grab the mailboxes */
1479         for (retries = 0; qlt->mbox_io_state != MBOX_STATE_READY;
1480             retries++) {
1481                 cv_wait(&qlt->mbox_cv, &qlt->mbox_lock);
1482                 if ((retries > 5) ||
1483                     (qlt->mbox_io_state == MBOX_STATE_UNKNOWN)) {
1484                         qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
1485                         mutex_exit(&qlt->mbox_lock);
1486                         goto poff_mbox_done;
1487                 }
1488         }
1489         qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
1490         mutex_exit(&qlt->mbox_lock);
1491 poff_mbox_done:;
1492         qlt->intr_sneak_counter = 10;
1493         mutex_enter(&qlt->intr_lock);
1494         (void) qlt_reset_chip(qlt);
1495         drv_usecwait(20);
1496         qlt->intr_sneak_counter = 0;
1497         mutex_exit(&qlt->intr_lock);
1498 
1499         return (FCT_SUCCESS);
1500 }
1501 
1502 static fct_status_t
1503 qlt_get_link_info(fct_local_port_t *port, fct_link_info_t *li)
1504 {
1505         qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
1506         mbox_cmd_t *mcp;
1507         fct_status_t fc_ret;
1508         fct_status_t ret;
1509         clock_t et;
1510 
1511         et = ddi_get_lbolt() + drv_usectohz(5000000);
1512         mcp = qlt_alloc_mailbox_command(qlt, 0);
1513 link_info_retry:
1514         mcp->to_fw[0] = MBC_GET_ID;
1515         mcp->to_fw[9] = 0;
1516         mcp->to_fw_mask |= BIT_0 | BIT_9;
1517         mcp->from_fw_mask |= BIT_0 | BIT_1 | BIT_2 | BIT_3 | BIT_6 | BIT_7;
1518         /* Issue mailbox to firmware */
1519         ret = qlt_mailbox_command(qlt, mcp);
1520         if (ret != QLT_SUCCESS) {
1521                 EL(qlt, "qlt_mailbox_command=20h status=%llxh\n", ret);
1522                 if ((mcp->from_fw[0] == 0x4005) && (mcp->from_fw[1] == 7)) {
1523                         /* Firmware is not ready */
1524                         if (ddi_get_lbolt() < et) {
1525                                 delay(drv_usectohz(50000));
1526                                 goto link_info_retry;
1527                         }
1528                 }
1529                 stmf_trace(qlt->qlt_port_alias, "GET ID mbox failed, ret=%llx "
1530                     "mb0=%x mb1=%x", ret, mcp->from_fw[0], mcp->from_fw[1]);
1531                 fc_ret = FCT_FAILURE;
1532         } else {
1533                 li->portid = ((uint32_t)(mcp->from_fw[2])) |
1534                     (((uint32_t)(mcp->from_fw[3])) << 16);
1535 
1536                 li->port_speed = qlt->link_speed;
1537                 switch (mcp->from_fw[6]) {
1538                 case 1:
1539                         li->port_topology = PORT_TOPOLOGY_PUBLIC_LOOP;
1540                         li->port_fca_flogi_done = 1;
1541                         break;
1542                 case 0:
1543                         li->port_topology = PORT_TOPOLOGY_PRIVATE_LOOP;
1544                         li->port_no_fct_flogi = 1;
1545                         break;
1546                 case 3:
1547                         li->port_topology = PORT_TOPOLOGY_FABRIC_PT_TO_PT;
1548                         li->port_fca_flogi_done = 1;
1549                         break;
1550                 case 2: /*FALLTHROUGH*/
1551                 case 4:
1552                         li->port_topology = PORT_TOPOLOGY_PT_TO_PT;
1553                         li->port_fca_flogi_done = 1;
1554                         break;
1555                 default:
1556                         li->port_topology = PORT_TOPOLOGY_UNKNOWN;
1557                         EL(qlt, "Unknown topology=%xh\n", mcp->from_fw[6]);
1558                 }
1559                 qlt->cur_topology = li->port_topology;
1560                 fc_ret = FCT_SUCCESS;
1561         }
1562         qlt_free_mailbox_command(qlt, mcp);
1563 
1564         if ((fc_ret == FCT_SUCCESS) && (li->port_fca_flogi_done)) {
1565                 mcp = qlt_alloc_mailbox_command(qlt, 64);
1566                 mcp->to_fw[0] = MBC_GET_PORT_DATABASE;
1567                 mcp->to_fw[1] = 0x7FE;
1568                 mcp->to_fw[9] = 0;
1569                 mcp->to_fw[10] = 0;
1570                 mcp->to_fw_mask |= BIT_0 | BIT_1 | BIT_9 | BIT_10;
1571                 fc_ret = qlt_mailbox_command(qlt, mcp);
1572                 if (fc_ret != QLT_SUCCESS) {
1573                         EL(qlt, "qlt_mailbox_command=64h status=%llxh\n",
1574                             fc_ret);
1575                         stmf_trace(qlt->qlt_port_alias, "Attempt to get port "
1576                             "database for F_port failed, ret = %llx", fc_ret);
1577                 } else {
1578                         uint8_t *p;
1579 
1580                         qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
1581                         p = mcp->dbuf->db_sglist[0].seg_addr;
1582                         bcopy(p + 0x18, li->port_rpwwn, 8);
1583                         bcopy(p + 0x20, li->port_rnwwn, 8);
1584                 }
1585                 qlt_free_mailbox_command(qlt, mcp);
1586         }
1587         return (fc_ret);
1588 }
1589 
1590 static int
1591 qlt_open(dev_t *devp, int flag, int otype, cred_t *credp)
1592 {
1593         int             instance;
1594         qlt_state_t     *qlt;
1595 
1596         if (otype != OTYP_CHR) {
1597                 return (EINVAL);
1598         }
1599 
1600         /*
1601          * Since this is for debugging only, only allow root to issue ioctl now
1602          */
1603         if (drv_priv(credp)) {
1604                 return (EPERM);
1605         }
1606 
1607         instance = (int)getminor(*devp);
1608         qlt = ddi_get_soft_state(qlt_state, instance);
1609         if (qlt == NULL) {
1610                 return (ENXIO);
1611         }
1612 
1613         mutex_enter(&qlt->qlt_ioctl_lock);
1614         if (qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_EXCL) {
1615                 /*
1616                  * It is already open for exclusive access.
1617                  * So shut the door on this caller.
1618                  */
1619                 mutex_exit(&qlt->qlt_ioctl_lock);
1620                 return (EBUSY);
1621         }
1622 
1623         if (flag & FEXCL) {
1624                 if (qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_OPEN) {
1625                         /*
1626                          * Exclusive operation not possible
1627                          * as it is already opened
1628                          */
1629                         mutex_exit(&qlt->qlt_ioctl_lock);
1630                         return (EBUSY);
1631                 }
1632                 qlt->qlt_ioctl_flags |= QLT_IOCTL_FLAG_EXCL;
1633         }
1634         qlt->qlt_ioctl_flags |= QLT_IOCTL_FLAG_OPEN;
1635         mutex_exit(&qlt->qlt_ioctl_lock);
1636 
1637         return (0);
1638 }
1639 
1640 /* ARGSUSED */
1641 static int
1642 qlt_close(dev_t dev, int flag, int otype, cred_t *credp)
1643 {
1644         int             instance;
1645         qlt_state_t     *qlt;
1646 
1647         if (otype != OTYP_CHR) {
1648                 return (EINVAL);
1649         }
1650 
1651         instance = (int)getminor(dev);
1652         qlt = ddi_get_soft_state(qlt_state, instance);
1653         if (qlt == NULL) {
1654                 return (ENXIO);
1655         }
1656 
1657         mutex_enter(&qlt->qlt_ioctl_lock);
1658         if ((qlt->qlt_ioctl_flags & QLT_IOCTL_FLAG_OPEN) == 0) {
1659                 mutex_exit(&qlt->qlt_ioctl_lock);
1660                 return (ENODEV);
1661         }
1662 
1663         /*
1664          * It looks there's one hole here, maybe there could several concurrent
1665          * shareed open session, but we never check this case.
1666          * But it will not hurt too much, disregard it now.
1667          */
1668         qlt->qlt_ioctl_flags &= ~QLT_IOCTL_FLAG_MASK;
1669         mutex_exit(&qlt->qlt_ioctl_lock);
1670 
1671         return (0);
1672 }
1673 
1674 /*
1675  * All of these ioctls are unstable interfaces which are meant to be used
1676  * in a controlled lab env. No formal testing will be (or needs to be) done
1677  * for these ioctls. Specially note that running with an additional
1678  * uploaded firmware is not supported and is provided here for test
1679  * purposes only.
1680  */
1681 /* ARGSUSED */
1682 static int
1683 qlt_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
1684     cred_t *credp, int *rval)
1685 {
1686         qlt_state_t     *qlt;
1687         int             ret = 0;
1688 #ifdef _LITTLE_ENDIAN
1689         int             i;
1690 #endif
1691         stmf_iocdata_t  *iocd;
1692         void            *ibuf = NULL;
1693         void            *obuf = NULL;
1694         uint32_t        *intp;
1695         qlt_fw_info_t   *fwi;
1696         mbox_cmd_t      *mcp;
1697         fct_status_t    st;
1698         char            info[QLT_INFO_LEN];
1699         fct_status_t    ret2;
1700 
1701         if (drv_priv(credp) != 0)
1702                 return (EPERM);
1703 
1704         qlt = ddi_get_soft_state(qlt_state, (int32_t)getminor(dev));
1705         ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
1706         if (ret)
1707                 return (ret);
1708         iocd->stmf_error = 0;
1709 
1710         switch (cmd) {
1711         case QLT_IOCTL_FETCH_FWDUMP:
1712                 if (iocd->stmf_obuf_size < QLT_FWDUMP_BUFSIZE) {
1713                         EL(qlt, "FETCH_FWDUMP obuf_size=%d < %d\n",
1714                             iocd->stmf_obuf_size, QLT_FWDUMP_BUFSIZE);
1715                         ret = EINVAL;
1716                         break;
1717                 }
1718                 mutex_enter(&qlt->qlt_ioctl_lock);
1719                 if (!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID)) {
1720                         mutex_exit(&qlt->qlt_ioctl_lock);
1721                         ret = ENODATA;
1722                         EL(qlt, "no fwdump\n");
1723                         iocd->stmf_error = QLTIO_NO_DUMP;
1724                         break;
1725                 }
1726                 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
1727                         mutex_exit(&qlt->qlt_ioctl_lock);
1728                         ret = EBUSY;
1729                         EL(qlt, "fwdump inprogress\n");
1730                         iocd->stmf_error = QLTIO_DUMP_INPROGRESS;
1731                         break;
1732                 }
1733                 if (qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER) {
1734                         mutex_exit(&qlt->qlt_ioctl_lock);
1735                         ret = EEXIST;
1736                         EL(qlt, "fwdump already fetched\n");
1737                         iocd->stmf_error = QLTIO_ALREADY_FETCHED;
1738                         break;
1739                 }
1740                 bcopy(qlt->qlt_fwdump_buf, obuf, QLT_FWDUMP_BUFSIZE);
1741                 qlt->qlt_ioctl_flags |= QLT_FWDUMP_FETCHED_BY_USER;
1742                 mutex_exit(&qlt->qlt_ioctl_lock);
1743 
1744                 break;
1745 
1746         case QLT_IOCTL_TRIGGER_FWDUMP:
1747                 if (qlt->qlt_state != FCT_STATE_ONLINE) {
1748                         ret = EACCES;
1749                         iocd->stmf_error = QLTIO_NOT_ONLINE;
1750                         break;
1751                 }
1752                 (void) snprintf(info, sizeof (info), "qlt_ioctl: qlt-%p, "
1753                     "user triggered FWDUMP with RFLAG_RESET", (void *)qlt);
1754                 if ((ret2 = fct_port_shutdown(qlt->qlt_port,
1755                     STMF_RFLAG_USER_REQUEST | STMF_RFLAG_RESET |
1756                     STMF_RFLAG_COLLECT_DEBUG_DUMP, info)) != FCT_SUCCESS) {
1757                         EL(qlt, "TRIGGER_FWDUMP fct_port_shutdown status="
1758                             "%llxh\n", ret2);
1759                         ret = EIO;
1760                 }
1761                 break;
1762         case QLT_IOCTL_UPLOAD_FW:
1763                 if ((iocd->stmf_ibuf_size < 1024) ||
1764                     (iocd->stmf_ibuf_size & 3)) {
1765                         EL(qlt, "UPLOAD_FW ibuf_size=%d < 1024\n",
1766                             iocd->stmf_ibuf_size);
1767                         ret = EINVAL;
1768                         iocd->stmf_error = QLTIO_INVALID_FW_SIZE;
1769                         break;
1770                 }
1771                 intp = (uint32_t *)ibuf;
1772 #ifdef _LITTLE_ENDIAN
1773                 for (i = 0; (i << 2) < iocd->stmf_ibuf_size; i++) {
1774                         intp[i] = BSWAP_32(intp[i]);
1775                 }
1776 #endif
1777                 if (((intp[3] << 2) >= iocd->stmf_ibuf_size) ||
1778                     (((intp[intp[3] + 3] + intp[3]) << 2) !=
1779                     iocd->stmf_ibuf_size)) {
1780                         EL(qlt, "UPLOAD_FW fw_size=%d >= %d\n", intp[3] << 2,
1781                             iocd->stmf_ibuf_size);
1782                         ret = EINVAL;
1783                         iocd->stmf_error = QLTIO_INVALID_FW_SIZE;
1784                         break;
1785                 }
1786                 if ((qlt->qlt_81xx_chip && ((intp[8] & 8) == 0)) ||
1787                     (qlt->qlt_25xx_chip && ((intp[8] & 4) == 0)) ||
1788                     (!qlt->qlt_25xx_chip && !qlt->qlt_81xx_chip &&
1789                     ((intp[8] & 3) == 0))) {
1790                         EL(qlt, "UPLOAD_FW fw_type=%d\n", intp[8]);
1791                         ret = EACCES;
1792                         iocd->stmf_error = QLTIO_INVALID_FW_TYPE;
1793                         break;
1794                 }
1795 
1796                 /* Everything looks ok, lets copy this firmware */
1797                 if (qlt->fw_code01) {
1798                         kmem_free(qlt->fw_code01, (qlt->fw_length01 +
1799                             qlt->fw_length02) << 2);
1800                         qlt->fw_code01 = NULL;
1801                 } else {
1802                         atomic_inc_32(&qlt_loaded_counter);
1803                 }
1804                 qlt->fw_length01 = intp[3];
1805                 qlt->fw_code01 = (uint32_t *)kmem_alloc(iocd->stmf_ibuf_size,
1806                     KM_SLEEP);
1807                 bcopy(intp, qlt->fw_code01, iocd->stmf_ibuf_size);
1808                 qlt->fw_addr01 = intp[2];
1809                 qlt->fw_code02 = &qlt->fw_code01[intp[3]];
1810                 qlt->fw_addr02 = qlt->fw_code02[2];
1811                 qlt->fw_length02 = qlt->fw_code02[3];
1812                 break;
1813 
1814         case QLT_IOCTL_CLEAR_FW:
1815                 if (qlt->fw_code01) {
1816                         kmem_free(qlt->fw_code01, (qlt->fw_length01 +
1817                             qlt->fw_length02) << 2);
1818                         qlt->fw_code01 = NULL;
1819                         atomic_dec_32(&qlt_loaded_counter);
1820                 }
1821                 break;
1822 
1823         case QLT_IOCTL_GET_FW_INFO:
1824                 if (iocd->stmf_obuf_size != sizeof (qlt_fw_info_t)) {
1825                         EL(qlt, "GET_FW_INFO obuf_size=%d != %d\n",
1826                             iocd->stmf_obuf_size, sizeof (qlt_fw_info_t));
1827                         ret = EINVAL;
1828                         break;
1829                 }
1830                 fwi = (qlt_fw_info_t *)obuf;
1831                 if (qlt->qlt_stay_offline) {
1832                         fwi->fwi_stay_offline = 1;
1833                 }
1834                 if (qlt->qlt_state == FCT_STATE_ONLINE) {
1835                         fwi->fwi_port_active = 1;
1836                 }
1837                 fwi->fwi_active_major = qlt->fw_major;
1838                 fwi->fwi_active_minor = qlt->fw_minor;
1839                 fwi->fwi_active_subminor = qlt->fw_subminor;
1840                 fwi->fwi_active_attr = qlt->fw_attr;
1841                 if (qlt->fw_code01) {
1842                         fwi->fwi_fw_uploaded = 1;
1843                         fwi->fwi_loaded_major = (uint16_t)qlt->fw_code01[4];
1844                         fwi->fwi_loaded_minor = (uint16_t)qlt->fw_code01[5];
1845                         fwi->fwi_loaded_subminor = (uint16_t)qlt->fw_code01[6];
1846                         fwi->fwi_loaded_attr = (uint16_t)qlt->fw_code01[7];
1847                 }
1848                 if (qlt->qlt_81xx_chip) {
1849                         fwi->fwi_default_major = (uint16_t)fw8100_code01[4];
1850                         fwi->fwi_default_minor = (uint16_t)fw8100_code01[5];
1851                         fwi->fwi_default_subminor = (uint16_t)fw8100_code01[6];
1852                         fwi->fwi_default_attr = (uint16_t)fw8100_code01[7];
1853                 } else if (qlt->qlt_25xx_chip) {
1854                         fwi->fwi_default_major = (uint16_t)fw2500_code01[4];
1855                         fwi->fwi_default_minor = (uint16_t)fw2500_code01[5];
1856                         fwi->fwi_default_subminor = (uint16_t)fw2500_code01[6];
1857                         fwi->fwi_default_attr = (uint16_t)fw2500_code01[7];
1858                 } else {
1859                         fwi->fwi_default_major = (uint16_t)fw2400_code01[4];
1860                         fwi->fwi_default_minor = (uint16_t)fw2400_code01[5];
1861                         fwi->fwi_default_subminor = (uint16_t)fw2400_code01[6];
1862                         fwi->fwi_default_attr = (uint16_t)fw2400_code01[7];
1863                 }
1864                 break;
1865 
1866         case QLT_IOCTL_STAY_OFFLINE:
1867                 if (!iocd->stmf_ibuf_size) {
1868                         EL(qlt, "STAY_OFFLINE ibuf_size=%d\n",
1869                             iocd->stmf_ibuf_size);
1870                         ret = EINVAL;
1871                         break;
1872                 }
1873                 if (*((char *)ibuf)) {
1874                         qlt->qlt_stay_offline = 1;
1875                 } else {
1876                         qlt->qlt_stay_offline = 0;
1877                 }
1878                 break;
1879 
1880         case QLT_IOCTL_MBOX:
1881                 if ((iocd->stmf_ibuf_size < sizeof (qlt_ioctl_mbox_t)) ||
1882                     (iocd->stmf_obuf_size < sizeof (qlt_ioctl_mbox_t))) {
1883                         EL(qlt, "IOCTL_MBOX ibuf_size=%d, obuf_size=%d\n",
1884                             iocd->stmf_ibuf_size, iocd->stmf_obuf_size);
1885                         ret = EINVAL;
1886                         break;
1887                 }
1888                 mcp = qlt_alloc_mailbox_command(qlt, 0);
1889                 if (mcp == NULL) {
1890                         EL(qlt, "IOCTL_MBOX mcp == NULL\n");
1891                         ret = ENOMEM;
1892                         break;
1893                 }
1894                 bcopy(ibuf, mcp, sizeof (qlt_ioctl_mbox_t));
1895                 st = qlt_mailbox_command(qlt, mcp);
1896                 bcopy(mcp, obuf, sizeof (qlt_ioctl_mbox_t));
1897                 qlt_free_mailbox_command(qlt, mcp);
1898                 if (st != QLT_SUCCESS) {
1899                         if ((st & (~((uint64_t)(0xFFFF)))) == QLT_MBOX_FAILED)
1900                                 st = QLT_SUCCESS;
1901                 }
1902                 if (st != QLT_SUCCESS) {
1903                         EL(qlt, "IOCTL_MBOX status=%xh\n", st);
1904                         ret = EIO;
1905                         switch (st) {
1906                         case QLT_MBOX_NOT_INITIALIZED:
1907                                 iocd->stmf_error = QLTIO_MBOX_NOT_INITIALIZED;
1908                                 break;
1909                         case QLT_MBOX_BUSY:
1910                                 iocd->stmf_error = QLTIO_CANT_GET_MBOXES;
1911                                 break;
1912                         case QLT_MBOX_TIMEOUT:
1913                                 iocd->stmf_error = QLTIO_MBOX_TIMED_OUT;
1914                                 break;
1915                         case QLT_MBOX_ABORTED:
1916                                 iocd->stmf_error = QLTIO_MBOX_ABORTED;
1917                                 break;
1918                         }
1919                 }
1920                 break;
1921 
1922         case QLT_IOCTL_ELOG:
1923                 qlt_dump_el_trace_buffer(qlt);
1924                 break;
1925 
1926         default:
1927                 EL(qlt, "Unknown ioctl-%xh\n", cmd);
1928                 ret = ENOTTY;
1929         }
1930 
1931         if (ret == 0) {
1932                 ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
1933         } else if (iocd->stmf_error) {
1934                 (void) stmf_copyout_iocdata(data, mode, iocd, obuf);
1935         }
1936         if (obuf) {
1937                 kmem_free(obuf, iocd->stmf_obuf_size);
1938                 obuf = NULL;
1939         }
1940         if (ibuf) {
1941                 kmem_free(ibuf, iocd->stmf_ibuf_size);
1942                 ibuf = NULL;
1943         }
1944         kmem_free(iocd, sizeof (stmf_iocdata_t));
1945         return (ret);
1946 }
1947 
1948 static fct_status_t
1949 qlt_force_lip(qlt_state_t *qlt)
1950 {
1951         mbox_cmd_t      *mcp;
1952         fct_status_t     rval;
1953 
1954         mcp = qlt_alloc_mailbox_command(qlt, 0);
1955         mcp->to_fw[0] = 0x0072;
1956         mcp->to_fw[1] = BIT_4;
1957         mcp->to_fw[3] = 1;
1958         mcp->to_fw_mask |= BIT_1 | BIT_3;
1959         rval = qlt_mailbox_command(qlt, mcp);
1960         if (rval != FCT_SUCCESS) {
1961                 EL(qlt, "qlt force lip MB failed: rval=%x", rval);
1962         } else {
1963                 if (mcp->from_fw[0] != 0x4000) {
1964                         QLT_LOG(qlt->qlt_port_alias, "qlt FLIP: fw[0]=%x",
1965                             mcp->from_fw[0]);
1966                         rval = FCT_FAILURE;
1967                 }
1968         }
1969         qlt_free_mailbox_command(qlt, mcp);
1970         return (rval);
1971 }
1972 
1973 static void
1974 qlt_ctl(struct fct_local_port *port, int cmd, void *arg)
1975 {
1976         stmf_change_status_t            st;
1977         stmf_state_change_info_t        *ssci = (stmf_state_change_info_t *)arg;
1978         qlt_state_t                     *qlt;
1979         fct_status_t                    ret;
1980 
1981         ASSERT((cmd == FCT_CMD_PORT_ONLINE) ||
1982             (cmd == FCT_CMD_PORT_OFFLINE) ||
1983             (cmd == FCT_CMD_FORCE_LIP) ||
1984             (cmd == FCT_ACK_PORT_ONLINE_COMPLETE) ||
1985             (cmd == FCT_ACK_PORT_OFFLINE_COMPLETE));
1986 
1987         qlt = (qlt_state_t *)port->port_fca_private;
1988         st.st_completion_status = FCT_SUCCESS;
1989         st.st_additional_info = NULL;
1990 
1991         switch (cmd) {
1992         case FCT_CMD_PORT_ONLINE:
1993                 if (qlt->qlt_state == FCT_STATE_ONLINE)
1994                         st.st_completion_status = STMF_ALREADY;
1995                 else if (qlt->qlt_state != FCT_STATE_OFFLINE)
1996                         st.st_completion_status = FCT_FAILURE;
1997                 if (st.st_completion_status == FCT_SUCCESS) {
1998                         qlt->qlt_state = FCT_STATE_ONLINING;
1999                         qlt->qlt_state_not_acked = 1;
2000                         st.st_completion_status = qlt_port_online(qlt);
2001                         if (st.st_completion_status != STMF_SUCCESS) {
2002                                 EL(qlt, "PORT_ONLINE status=%xh\n",
2003                                     st.st_completion_status);
2004                                 qlt->qlt_state = FCT_STATE_OFFLINE;
2005                                 qlt->qlt_state_not_acked = 0;
2006                         } else {
2007                                 qlt->qlt_state = FCT_STATE_ONLINE;
2008                         }
2009                 }
2010                 fct_ctl(port->port_lport, FCT_CMD_PORT_ONLINE_COMPLETE, &st);
2011                 qlt->qlt_change_state_flags = 0;
2012                 break;
2013 
2014         case FCT_CMD_PORT_OFFLINE:
2015                 if (qlt->qlt_state == FCT_STATE_OFFLINE) {
2016                         st.st_completion_status = STMF_ALREADY;
2017                 } else if (qlt->qlt_state != FCT_STATE_ONLINE) {
2018                         st.st_completion_status = FCT_FAILURE;
2019                 }
2020                 if (st.st_completion_status == FCT_SUCCESS) {
2021                         qlt->qlt_state = FCT_STATE_OFFLINING;
2022                         qlt->qlt_state_not_acked = 1;
2023 
2024                         if (ssci->st_rflags & STMF_RFLAG_COLLECT_DEBUG_DUMP) {
2025                                 (void) qlt_firmware_dump(port, ssci);
2026                         }
2027                         qlt->qlt_change_state_flags = (uint32_t)ssci->st_rflags;
2028                         st.st_completion_status = qlt_port_offline(qlt);
2029                         if (st.st_completion_status != STMF_SUCCESS) {
2030                                 EL(qlt, "PORT_OFFLINE status=%xh\n",
2031                                     st.st_completion_status);
2032                                 qlt->qlt_state = FCT_STATE_ONLINE;
2033                                 qlt->qlt_state_not_acked = 0;
2034                         } else {
2035                                 qlt->qlt_state = FCT_STATE_OFFLINE;
2036                         }
2037                 }
2038                 fct_ctl(port->port_lport, FCT_CMD_PORT_OFFLINE_COMPLETE, &st);
2039                 break;
2040 
2041         case FCT_ACK_PORT_ONLINE_COMPLETE:
2042                 qlt->qlt_state_not_acked = 0;
2043                 break;
2044 
2045         case FCT_ACK_PORT_OFFLINE_COMPLETE:
2046                 qlt->qlt_state_not_acked = 0;
2047                 if ((qlt->qlt_change_state_flags & STMF_RFLAG_RESET) &&
2048                     (qlt->qlt_stay_offline == 0)) {
2049                         if ((ret = fct_port_initialize(port,
2050                             qlt->qlt_change_state_flags,
2051                             "qlt_ctl FCT_ACK_PORT_OFFLINE_COMPLETE "
2052                             "with RLFLAG_RESET")) != FCT_SUCCESS) {
2053                                 EL(qlt, "fct_port_initialize status=%llxh\n",
2054                                     ret);
2055                                 cmn_err(CE_WARN, "qlt_ctl: "
2056                                     "fct_port_initialize failed, please use "
2057                                     "stmfstate to start the port-%s manualy",
2058                                     qlt->qlt_port_alias);
2059                         }
2060                 }
2061                 break;
2062 
2063         case FCT_CMD_FORCE_LIP:
2064                 if (qlt->qlt_81xx_chip) {
2065                         EL(qlt, "force lip is an unsupported command "
2066                             "for this adapter type\n");
2067                 } else {
2068                         *((fct_status_t *)arg) = qlt_force_lip(qlt);
2069                         EL(qlt, "forcelip done\n");
2070                 }
2071                 break;
2072 
2073         default:
2074                 EL(qlt, "unsupport cmd - 0x%02X", cmd);
2075                 break;
2076         }
2077 }
2078 
2079 /* ARGSUSED */
2080 static fct_status_t
2081 qlt_do_flogi(fct_local_port_t *port, fct_flogi_xchg_t *fx)
2082 {
2083         qlt_state_t     *qlt = (qlt_state_t *)port->port_fca_private;
2084 
2085         EL(qlt, "FLOGI requested not supported\n");
2086         cmn_err(CE_WARN, "qlt: FLOGI requested (not supported)");
2087         return (FCT_FAILURE);
2088 }
2089 
2090 /*
2091  * Return a pointer to n entries in the request queue. Assumes that
2092  * request queue lock is held. Does a very short busy wait if
2093  * less/zero entries are available. Retuns NULL if it still cannot
2094  * fullfill the request.
2095  * **CALL qlt_submit_req_entries() BEFORE DROPPING THE LOCK**
2096  */
2097 caddr_t
2098 qlt_get_req_entries(qlt_state_t *qlt, uint32_t n)
2099 {
2100         int try = 0;
2101 
2102         while (qlt->req_available < n) {
2103                 uint32_t val1, val2, val3;
2104                 val1 = REG_RD32(qlt, REG_REQ_OUT_PTR);
2105                 val2 = REG_RD32(qlt, REG_REQ_OUT_PTR);
2106                 val3 = REG_RD32(qlt, REG_REQ_OUT_PTR);
2107                 if ((val1 != val2) || (val2 != val3))
2108                         continue;
2109 
2110                 qlt->req_ndx_from_fw = val1;
2111                 qlt->req_available = REQUEST_QUEUE_ENTRIES - 1 -
2112                     ((qlt->req_ndx_to_fw - qlt->req_ndx_from_fw) &
2113                     (REQUEST_QUEUE_ENTRIES - 1));
2114                 if (qlt->req_available < n) {
2115                         if (try < 2) {
2116                                 drv_usecwait(100);
2117                                 try++;
2118                                 continue;
2119                         } else {
2120                                 stmf_trace(qlt->qlt_port_alias,
2121                                     "Req Q is full");
2122                                 return (NULL);
2123                         }
2124                 }
2125                 break;
2126         }
2127         /* We dont change anything until the entries are sumitted */
2128         return (&qlt->req_ptr[qlt->req_ndx_to_fw << 6]);
2129 }
2130 
2131 /*
2132  * updates the req in ptr to fw. Assumes that req lock is held.
2133  */
2134 void
2135 qlt_submit_req_entries(qlt_state_t *qlt, uint32_t n)
2136 {
2137         ASSERT(n >= 1);
2138         qlt->req_ndx_to_fw += n;
2139         qlt->req_ndx_to_fw &= REQUEST_QUEUE_ENTRIES - 1;
2140         qlt->req_available -= n;
2141         REG_WR32(qlt, REG_REQ_IN_PTR, qlt->req_ndx_to_fw);
2142 }
2143 
2144 
2145 /*
2146  * Return a pointer to n entries in the priority request queue. Assumes that
2147  * priority request queue lock is held. Does a very short busy wait if
2148  * less/zero entries are available. Retuns NULL if it still cannot
2149  * fullfill the request.
2150  * **CALL qlt_submit_preq_entries() BEFORE DROPPING THE LOCK**
2151  */
2152 caddr_t
2153 qlt_get_preq_entries(qlt_state_t *qlt, uint32_t n)
2154 {
2155         int try = 0;
2156         uint32_t req_available = PRIORITY_QUEUE_ENTRIES - 1 -
2157             ((qlt->preq_ndx_to_fw - qlt->preq_ndx_from_fw) &
2158             (PRIORITY_QUEUE_ENTRIES - 1));
2159 
2160         while (req_available < n) {
2161                 uint32_t val1, val2, val3;
2162                 val1 = REG_RD32(qlt, REG_PREQ_OUT_PTR);
2163                 val2 = REG_RD32(qlt, REG_PREQ_OUT_PTR);
2164                 val3 = REG_RD32(qlt, REG_PREQ_OUT_PTR);
2165                 if ((val1 != val2) || (val2 != val3))
2166                         continue;
2167 
2168                 qlt->preq_ndx_from_fw = val1;
2169                 req_available = PRIORITY_QUEUE_ENTRIES - 1 -
2170                     ((qlt->preq_ndx_to_fw - qlt->preq_ndx_from_fw) &
2171                     (PRIORITY_QUEUE_ENTRIES - 1));
2172                 if (req_available < n) {
2173                         if (try < 2) {
2174                                 drv_usecwait(100);
2175                                 try++;
2176                                 continue;
2177                         } else {
2178                                 return (NULL);
2179                         }
2180                 }
2181                 break;
2182         }
2183         /* We dont change anything until the entries are sumitted */
2184         return (&qlt->preq_ptr[qlt->preq_ndx_to_fw << 6]);
2185 }
2186 
2187 /*
2188  * updates the req in ptr to fw. Assumes that req lock is held.
2189  */
2190 void
2191 qlt_submit_preq_entries(qlt_state_t *qlt, uint32_t n)
2192 {
2193         ASSERT(n >= 1);
2194         qlt->preq_ndx_to_fw += n;
2195         qlt->preq_ndx_to_fw &= PRIORITY_QUEUE_ENTRIES - 1;
2196         REG_WR32(qlt, REG_PREQ_IN_PTR, qlt->preq_ndx_to_fw);
2197 }
2198 
2199 /*
2200  * - Should not be called from Interrupt.
2201  * - A very hardware specific function. Does not touch driver state.
2202  * - Assumes that interrupts are disabled or not there.
2203  * - Expects that the caller makes sure that all activity has stopped
2204  *   and its ok now to go ahead and reset the chip. Also the caller
2205  *   takes care of post reset damage control.
2206  * - called by initialize adapter() and dump_fw(for reset only).
2207  * - During attach() nothing much is happening and during initialize_adapter()
2208  *   the function (caller) does all the housekeeping so that this function
2209  *   can execute in peace.
2210  * - Returns 0 on success.
2211  */
2212 static fct_status_t
2213 qlt_reset_chip(qlt_state_t *qlt)
2214 {
2215         int cntr;
2216 
2217         EL(qlt, "initiated\n");
2218 
2219         /* XXX: Switch off LEDs */
2220 
2221         /* Disable Interrupts */
2222         REG_WR32(qlt, REG_INTR_CTRL, 0);
2223         (void) REG_RD32(qlt, REG_INTR_CTRL);
2224         /* Stop DMA */
2225         REG_WR32(qlt, REG_CTRL_STATUS, DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL);
2226 
2227         /* Wait for DMA to be stopped */
2228         cntr = 0;
2229         while (REG_RD32(qlt, REG_CTRL_STATUS) & DMA_ACTIVE_STATUS) {
2230                 delay(drv_usectohz(10000)); /* mostly 10ms is 1 tick */
2231                 cntr++;
2232                 /* 3 sec should be more than enough */
2233                 if (cntr == 300)
2234                         return (QLT_DMA_STUCK);
2235         }
2236 
2237         /* Reset the Chip */
2238         REG_WR32(qlt, REG_CTRL_STATUS,
2239             DMA_SHUTDOWN_CTRL | PCI_X_XFER_CTRL | CHIP_SOFT_RESET);
2240 
2241         qlt->qlt_link_up = 0;
2242 
2243         drv_usecwait(100);
2244 
2245         /* Wait for ROM firmware to initialize (0x0000) in mailbox 0 */
2246         cntr = 0;
2247         while (REG_RD16(qlt, REG_MBOX(0)) != 0) {
2248                 delay(drv_usectohz(10000));
2249                 cntr++;
2250                 /* 3 sec should be more than enough */
2251                 if (cntr == 300)
2252                         return (QLT_ROM_STUCK);
2253         }
2254         /* Disable Interrupts (Probably not needed) */
2255         REG_WR32(qlt, REG_INTR_CTRL, 0);
2256 
2257         return (QLT_SUCCESS);
2258 }
2259 /*
2260  * - Should not be called from Interrupt.
2261  * - A very hardware specific function. Does not touch driver state.
2262  * - Assumes that interrupts are disabled or not there.
2263  * - Expects that the caller makes sure that all activity has stopped
2264  *   and its ok now to go ahead and reset the chip. Also the caller
2265  *   takes care of post reset damage control.
2266  * - called by initialize adapter() and dump_fw(for reset only).
2267  * - During attach() nothing much is happening and during initialize_adapter()
2268  *   the function (caller) does all the housekeeping so that this function
2269  *   can execute in peace.
2270  * - Returns 0 on success.
2271  */
2272 static fct_status_t
2273 qlt_download_fw(qlt_state_t *qlt)
2274 {
2275         uint32_t start_addr;
2276         fct_status_t ret;
2277 
2278         EL(qlt, "initiated\n");
2279 
2280         (void) qlt_reset_chip(qlt);
2281 
2282         if (qlt->qlt_81xx_chip) {
2283                 qlt_mps_reset(qlt);
2284         }
2285 
2286         /* Load the two segments */
2287         if (qlt->fw_code01 != NULL) {
2288                 ret = qlt_load_risc_ram(qlt, qlt->fw_code01, qlt->fw_length01,
2289                     qlt->fw_addr01);
2290                 if (ret == QLT_SUCCESS) {
2291                         ret = qlt_load_risc_ram(qlt, qlt->fw_code02,
2292                             qlt->fw_length02, qlt->fw_addr02);
2293                 }
2294                 start_addr = qlt->fw_addr01;
2295         } else if (qlt->qlt_81xx_chip) {
2296                 ret = qlt_load_risc_ram(qlt, fw8100_code01, fw8100_length01,
2297                     fw8100_addr01);
2298                 if (ret == QLT_SUCCESS) {
2299                         ret = qlt_load_risc_ram(qlt, fw8100_code02,
2300                             fw8100_length02, fw8100_addr02);
2301                 }
2302                 start_addr = fw8100_addr01;
2303         } else if (qlt->qlt_25xx_chip) {
2304                 ret = qlt_load_risc_ram(qlt, fw2500_code01, fw2500_length01,
2305                     fw2500_addr01);
2306                 if (ret == QLT_SUCCESS) {
2307                         ret = qlt_load_risc_ram(qlt, fw2500_code02,
2308                             fw2500_length02, fw2500_addr02);
2309                 }
2310                 start_addr = fw2500_addr01;
2311         } else {
2312                 ret = qlt_load_risc_ram(qlt, fw2400_code01, fw2400_length01,
2313                     fw2400_addr01);
2314                 if (ret == QLT_SUCCESS) {
2315                         ret = qlt_load_risc_ram(qlt, fw2400_code02,
2316                             fw2400_length02, fw2400_addr02);
2317                 }
2318                 start_addr = fw2400_addr01;
2319         }
2320         if (ret != QLT_SUCCESS) {
2321                 EL(qlt, "qlt_load_risc_ram status=%llxh\n", ret);
2322                 return (ret);
2323         }
2324 
2325         /* Verify Checksum */
2326         REG_WR16(qlt, REG_MBOX(0), MBC_VERIFY_CHECKSUM);
2327         REG_WR16(qlt, REG_MBOX(1), MSW(start_addr));
2328         REG_WR16(qlt, REG_MBOX(2), LSW(start_addr));
2329         ret = qlt_raw_mailbox_command(qlt);
2330         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2331         if (ret != QLT_SUCCESS) {
2332                 EL(qlt, "qlt_raw_mailbox_command=7h status=%llxh\n", ret);
2333                 return (ret);
2334         }
2335 
2336         /* Execute firmware */
2337         REG_WR16(qlt, REG_MBOX(0), MBC_EXECUTE_FIRMWARE);
2338         REG_WR16(qlt, REG_MBOX(1), MSW(start_addr));
2339         REG_WR16(qlt, REG_MBOX(2), LSW(start_addr));
2340         REG_WR16(qlt, REG_MBOX(3), 0);
2341         REG_WR16(qlt, REG_MBOX(4), 1);  /* 25xx enable additional credits */
2342         ret = qlt_raw_mailbox_command(qlt);
2343         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2344         if (ret != QLT_SUCCESS) {
2345                 EL(qlt, "qlt_raw_mailbox_command=2h status=%llxh\n", ret);
2346                 return (ret);
2347         }
2348 
2349         /* Get revisions (About Firmware) */
2350         REG_WR16(qlt, REG_MBOX(0), MBC_ABOUT_FIRMWARE);
2351         ret = qlt_raw_mailbox_command(qlt);
2352         qlt->fw_major = REG_RD16(qlt, REG_MBOX(1));
2353         qlt->fw_minor = REG_RD16(qlt, REG_MBOX(2));
2354         qlt->fw_subminor = REG_RD16(qlt, REG_MBOX(3));
2355         qlt->fw_endaddrlo = REG_RD16(qlt, REG_MBOX(4));
2356         qlt->fw_endaddrhi = REG_RD16(qlt, REG_MBOX(5));
2357         qlt->fw_attr = REG_RD16(qlt, REG_MBOX(6));
2358         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2359         if (ret != QLT_SUCCESS) {
2360                 EL(qlt, "qlt_raw_mailbox_command=8h status=%llxh\n", ret);
2361                 return (ret);
2362         }
2363 
2364         return (QLT_SUCCESS);
2365 }
2366 
2367 /*
2368  * Used only from qlt_download_fw().
2369  */
2370 static fct_status_t
2371 qlt_load_risc_ram(qlt_state_t *qlt, uint32_t *host_addr,
2372                                 uint32_t word_count, uint32_t risc_addr)
2373 {
2374         uint32_t words_sent = 0;
2375         uint32_t words_being_sent;
2376         uint32_t *cur_host_addr;
2377         uint32_t cur_risc_addr;
2378         uint64_t da;
2379         fct_status_t ret;
2380 
2381         while (words_sent < word_count) {
2382                 cur_host_addr = &(host_addr[words_sent]);
2383                 cur_risc_addr = risc_addr + (words_sent << 2);
2384                 words_being_sent = min(word_count - words_sent,
2385                     TOTAL_DMA_MEM_SIZE >> 2);
2386                 ddi_rep_put32(qlt->queue_mem_acc_handle, cur_host_addr,
2387                     (uint32_t *)qlt->queue_mem_ptr, words_being_sent,
2388                     DDI_DEV_AUTOINCR);
2389                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, 0,
2390                     words_being_sent << 2, DDI_DMA_SYNC_FORDEV);
2391                 da = qlt->queue_mem_cookie.dmac_laddress;
2392                 REG_WR16(qlt, REG_MBOX(0), MBC_LOAD_RAM_EXTENDED);
2393                 REG_WR16(qlt, REG_MBOX(1), LSW(risc_addr));
2394                 REG_WR16(qlt, REG_MBOX(8), MSW(cur_risc_addr));
2395                 REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
2396                 REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
2397                 REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
2398                 REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
2399                 REG_WR16(qlt, REG_MBOX(5), LSW(words_being_sent));
2400                 REG_WR16(qlt, REG_MBOX(4), MSW(words_being_sent));
2401                 ret = qlt_raw_mailbox_command(qlt);
2402                 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2403                 if (ret != QLT_SUCCESS) {
2404                         EL(qlt, "qlt_raw_mailbox_command=0Bh status=%llxh\n",
2405                             ret);
2406                         return (ret);
2407                 }
2408                 words_sent += words_being_sent;
2409         }
2410         return (QLT_SUCCESS);
2411 }
2412 
2413 /*
2414  * Not used during normal operation. Only during driver init.
2415  * Assumes that interrupts are disabled and mailboxes are loaded.
2416  * Just triggers the mailbox command an waits for the completion.
2417  * Also expects that There is nothing else going on and we will only
2418  * get back a mailbox completion from firmware.
2419  * ---DOES NOT CLEAR INTERRUPT---
2420  * Used only from the code path originating from
2421  * qlt_reset_chip_and_download_fw()
2422  */
2423 static fct_status_t
2424 qlt_raw_mailbox_command(qlt_state_t *qlt)
2425 {
2426         int cntr = 0;
2427         uint32_t status;
2428 
2429         REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
2430         while ((REG_RD32(qlt, REG_INTR_STATUS) & RISC_PCI_INTR_REQUEST) == 0) {
2431                 cntr++;
2432                 if (cntr == 100) {
2433                         return (QLT_MAILBOX_STUCK);
2434                 }
2435                 delay(drv_usectohz(10000));
2436         }
2437         status = (REG_RD32(qlt, REG_RISC_STATUS) & FW_INTR_STATUS_MASK);
2438 
2439         if ((status == ROM_MBX_CMD_SUCCESSFUL) ||
2440             (status == ROM_MBX_CMD_NOT_SUCCESSFUL) ||
2441             (status == MBX_CMD_SUCCESSFUL) ||
2442             (status == MBX_CMD_NOT_SUCCESSFUL)) {
2443                 uint16_t mbox0 = REG_RD16(qlt, REG_MBOX(0));
2444                 if (mbox0 == QLT_MBX_CMD_SUCCESS) {
2445                         return (QLT_SUCCESS);
2446                 } else {
2447                         return (QLT_MBOX_FAILED | mbox0);
2448                 }
2449         }
2450         /* This is unexpected, dump a message */
2451         cmn_err(CE_WARN, "qlt(%d): Unexpect intr status %llx",
2452             ddi_get_instance(qlt->dip), (unsigned long long)status);
2453         return (QLT_UNEXPECTED_RESPONSE);
2454 }
2455 
2456 static mbox_cmd_t *
2457 qlt_alloc_mailbox_command(qlt_state_t *qlt, uint32_t dma_size)
2458 {
2459         mbox_cmd_t *mcp;
2460 
2461         mcp = (mbox_cmd_t *)kmem_zalloc(sizeof (mbox_cmd_t), KM_SLEEP);
2462         if (dma_size) {
2463                 qlt_dmem_bctl_t *bctl;
2464                 uint64_t da;
2465 
2466                 mcp->dbuf = qlt_i_dmem_alloc(qlt, dma_size, &dma_size, 0);
2467                 if (mcp->dbuf == NULL) {
2468                         kmem_free(mcp, sizeof (*mcp));
2469                         return (NULL);
2470                 }
2471                 mcp->dbuf->db_data_size = dma_size;
2472                 ASSERT(mcp->dbuf->db_sglist_length == 1);
2473 
2474                 bctl = (qlt_dmem_bctl_t *)mcp->dbuf->db_port_private;
2475                 da = bctl->bctl_dev_addr;
2476                 /* This is the most common initialization of dma ptrs */
2477                 mcp->to_fw[3] = LSW(LSD(da));
2478                 mcp->to_fw[2] = MSW(LSD(da));
2479                 mcp->to_fw[7] = LSW(MSD(da));
2480                 mcp->to_fw[6] = MSW(MSD(da));
2481                 mcp->to_fw_mask |= BIT_2 | BIT_3 | BIT_7 | BIT_6;
2482         }
2483         mcp->to_fw_mask |= BIT_0;
2484         mcp->from_fw_mask |= BIT_0;
2485         return (mcp);
2486 }
2487 
2488 void
2489 qlt_free_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp)
2490 {
2491         if (mcp->dbuf)
2492                 qlt_i_dmem_free(qlt, mcp->dbuf);
2493         kmem_free(mcp, sizeof (*mcp));
2494 }
2495 
2496 /*
2497  * This can sleep. Should never be called from interrupt context.
2498  */
2499 static fct_status_t
2500 qlt_mailbox_command(qlt_state_t *qlt, mbox_cmd_t *mcp)
2501 {
2502         int     retries;
2503         int     i;
2504         char    info[QLT_INFO_LEN];
2505 
2506         if (curthread->t_flag & T_INTR_THREAD) {
2507                 ASSERT(0);
2508                 return (QLT_MBOX_FAILED);
2509         }
2510 
2511         mutex_enter(&qlt->mbox_lock);
2512         /* See if mailboxes are still uninitialized */
2513         if (qlt->mbox_io_state == MBOX_STATE_UNKNOWN) {
2514                 mutex_exit(&qlt->mbox_lock);
2515                 return (QLT_MBOX_NOT_INITIALIZED);
2516         }
2517 
2518         /* Wait to grab the mailboxes */
2519         for (retries = 0; qlt->mbox_io_state != MBOX_STATE_READY;
2520             retries++) {
2521                 cv_wait(&qlt->mbox_cv, &qlt->mbox_lock);
2522                 if ((retries > 5) ||
2523                     (qlt->mbox_io_state == MBOX_STATE_UNKNOWN)) {
2524                         mutex_exit(&qlt->mbox_lock);
2525                         return (QLT_MBOX_BUSY);
2526                 }
2527         }
2528         /* Make sure we always ask for mailbox 0 */
2529         mcp->from_fw_mask |= BIT_0;
2530 
2531         /* Load mailboxes, set state and generate RISC interrupt */
2532         qlt->mbox_io_state = MBOX_STATE_CMD_RUNNING;
2533         qlt->mcp = mcp;
2534         for (i = 0; i < MAX_MBOXES; i++) {
2535                 if (mcp->to_fw_mask & ((uint32_t)1 << i))
2536                         REG_WR16(qlt, REG_MBOX(i), mcp->to_fw[i]);
2537         }
2538         REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_HOST_TO_RISC_INTR));
2539 
2540 qlt_mbox_wait_loop:;
2541         /* Wait for mailbox command completion */
2542         if (cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock, ddi_get_lbolt()
2543             + drv_usectohz(MBOX_TIMEOUT)) < 0) {
2544                 (void) snprintf(info, sizeof (info),
2545                     "qlt_mailbox_command: qlt-%p, "
2546                     "cmd-0x%02X timed out", (void *)qlt, qlt->mcp->to_fw[0]);
2547                 qlt->mcp = NULL;
2548                 qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
2549                 mutex_exit(&qlt->mbox_lock);
2550 
2551                 /*
2552                  * XXX Throw HBA fatal error event
2553                  */
2554                 (void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR |
2555                     STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
2556                 return (QLT_MBOX_TIMEOUT);
2557         }
2558         if (qlt->mbox_io_state == MBOX_STATE_CMD_RUNNING)
2559                 goto qlt_mbox_wait_loop;
2560 
2561         qlt->mcp = NULL;
2562 
2563         /* Make sure its a completion */
2564         if (qlt->mbox_io_state != MBOX_STATE_CMD_DONE) {
2565                 ASSERT(qlt->mbox_io_state == MBOX_STATE_UNKNOWN);
2566                 mutex_exit(&qlt->mbox_lock);
2567                 return (QLT_MBOX_ABORTED);
2568         }
2569 
2570         /* MBox command completed. Clear state, retuen based on mbox 0 */
2571         /* Mailboxes are already loaded by interrupt routine */
2572         qlt->mbox_io_state = MBOX_STATE_READY;
2573         mutex_exit(&qlt->mbox_lock);
2574         if (mcp->from_fw[0] != QLT_MBX_CMD_SUCCESS)
2575                 return (QLT_MBOX_FAILED | mcp->from_fw[0]);
2576 
2577         return (QLT_SUCCESS);
2578 }
2579 
2580 /*
2581  * **SHOULD ONLY BE CALLED FROM INTERRUPT CONTEXT. DO NOT CALL ELSEWHERE**
2582  */
2583 /* ARGSUSED */
2584 static uint_t
2585 qlt_isr(caddr_t arg, caddr_t arg2)
2586 {
2587         qlt_state_t     *qlt = (qlt_state_t *)arg;
2588         uint32_t        risc_status, intr_type;
2589         int             i;
2590         int             intr_loop_count;
2591         char            info[QLT_INFO_LEN];
2592 
2593         risc_status = REG_RD32(qlt, REG_RISC_STATUS);
2594         if (!mutex_tryenter(&qlt->intr_lock)) {
2595                 /*
2596                  * Normally we will always get this lock. If tryenter is
2597                  * failing then it means that driver is trying to do
2598                  * some cleanup and is masking the intr but some intr
2599                  * has sneaked in between. See if our device has generated
2600                  * this intr. If so then wait a bit and return claimed.
2601                  * If not then return claimed if this is the 1st instance
2602                  * of a interrupt after driver has grabbed the lock.
2603                  */
2604                 if (risc_status & BIT_15) {
2605                         drv_usecwait(10);
2606                         return (DDI_INTR_CLAIMED);
2607                 } else if (qlt->intr_sneak_counter) {
2608                         qlt->intr_sneak_counter--;
2609                         return (DDI_INTR_CLAIMED);
2610                 } else {
2611                         return (DDI_INTR_UNCLAIMED);
2612                 }
2613         }
2614         if (((risc_status & BIT_15) == 0) ||
2615             (qlt->qlt_intr_enabled == 0)) {
2616                 /*
2617                  * This might be a pure coincedence that we are operating
2618                  * in a interrupt disabled mode and another device
2619                  * sharing the interrupt line has generated an interrupt
2620                  * while an interrupt from our device might be pending. Just
2621                  * ignore it and let the code handling the interrupt
2622                  * disabled mode handle it.
2623                  */
2624                 mutex_exit(&qlt->intr_lock);
2625                 return (DDI_INTR_UNCLAIMED);
2626         }
2627 
2628         /*
2629          * XXX take care for MSI case. disable intrs
2630          * Its gonna be complicated because of the max iterations.
2631          * as hba will have posted the intr which did not go on PCI
2632          * but we did not service it either because of max iterations.
2633          * Maybe offload the intr on a different thread.
2634          */
2635         intr_loop_count = 0;
2636 
2637         REG_WR32(qlt, REG_INTR_CTRL, 0);
2638 
2639 intr_again:;
2640 
2641         /* check for risc pause */
2642         if (risc_status & BIT_8) {
2643                 EL(qlt, "Risc Pause status=%xh\n", risc_status);
2644                 cmn_err(CE_WARN, "qlt(%d): Risc Pause %08x",
2645                     qlt->instance, risc_status);
2646                 (void) snprintf(info, sizeof (info), "Risc Pause %08x",
2647                     risc_status);
2648                 (void) fct_port_shutdown(qlt->qlt_port,
2649                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
2650                     STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
2651         }
2652 
2653         /* First check for high performance path */
2654         intr_type = risc_status & 0xff;
2655         if (intr_type == 0x1D) {
2656                 qlt->atio_ndx_from_fw = (uint16_t)
2657                     REG_RD32(qlt, REG_ATIO_IN_PTR);
2658                 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2659                 qlt->resp_ndx_from_fw = risc_status >> 16;
2660                 qlt_handle_atio_queue_update(qlt);
2661                 qlt_handle_resp_queue_update(qlt);
2662         } else if (intr_type == 0x1C) {
2663                 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2664                 qlt->atio_ndx_from_fw = (uint16_t)(risc_status >> 16);
2665                 qlt_handle_atio_queue_update(qlt);
2666         } else if (intr_type == 0x13) {
2667                 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2668                 qlt->resp_ndx_from_fw = risc_status >> 16;
2669                 qlt_handle_resp_queue_update(qlt);
2670         } else if (intr_type == 0x12) {
2671                 uint16_t code = (uint16_t)(risc_status >> 16);
2672                 uint16_t mbox1 = REG_RD16(qlt, REG_MBOX(1));
2673                 uint16_t mbox2 = REG_RD16(qlt, REG_MBOX(2));
2674                 uint16_t mbox3 = REG_RD16(qlt, REG_MBOX(3));
2675                 uint16_t mbox4 = REG_RD16(qlt, REG_MBOX(4));
2676                 uint16_t mbox5 = REG_RD16(qlt, REG_MBOX(5));
2677                 uint16_t mbox6 = REG_RD16(qlt, REG_MBOX(6));
2678 
2679                 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2680                 stmf_trace(qlt->qlt_port_alias, "Async event %x mb1=%x mb2=%x,"
2681                     " mb3=%x, mb5=%x, mb6=%x", code, mbox1, mbox2, mbox3,
2682                     mbox5, mbox6);
2683                 EL(qlt, "Async event %x mb1=%x mb2=%x, mb3=%x, mb5=%x, mb6=%x",
2684                     code, mbox1, mbox2, mbox3, mbox5, mbox6);
2685 
2686                 if ((code == 0x8030) || (code == 0x8010) || (code == 0x8013)) {
2687                         if (qlt->qlt_link_up) {
2688                                 fct_handle_event(qlt->qlt_port,
2689                                     FCT_EVENT_LINK_RESET, 0, 0);
2690                         }
2691                 } else if (code == 0x8012) {
2692                         qlt->qlt_link_up = 0;
2693                         fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_DOWN,
2694                             0, 0);
2695                 } else if (code == 0x8011) {
2696                         switch (mbox1) {
2697                         case 0: qlt->link_speed = PORT_SPEED_1G;
2698                                 break;
2699                         case 1: qlt->link_speed = PORT_SPEED_2G;
2700                                 break;
2701                         case 3: qlt->link_speed = PORT_SPEED_4G;
2702                                 break;
2703                         case 4: qlt->link_speed = PORT_SPEED_8G;
2704                                 break;
2705                         case 0x13: qlt->link_speed = PORT_SPEED_10G;
2706                                 break;
2707                         default:
2708                                 qlt->link_speed = PORT_SPEED_UNKNOWN;
2709                         }
2710                         qlt->qlt_link_up = 1;
2711                         fct_handle_event(qlt->qlt_port, FCT_EVENT_LINK_UP,
2712                             0, 0);
2713                 } else if ((code == 0x8002) || (code == 0x8003) ||
2714                     (code == 0x8004) || (code == 0x8005)) {
2715                         (void) snprintf(info, sizeof (info),
2716                             "Got %04x, mb1=%x mb2=%x mb5=%x mb6=%x",
2717                             code, mbox1, mbox2, mbox5, mbox6);
2718                         (void) fct_port_shutdown(qlt->qlt_port,
2719                             STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
2720                             STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
2721                 } else if (code == 0x800F) {
2722                         (void) snprintf(info, sizeof (info),
2723                             "Got 800F, mb1=%x mb2=%x mb3=%x",
2724                             mbox1, mbox2, mbox3);
2725 
2726                         if (mbox1 != 1) {
2727                                 /* issue "verify fw" */
2728                                 qlt_verify_fw(qlt);
2729                         }
2730                 } else if (code == 0x8101) {
2731                         (void) snprintf(info, sizeof (info),
2732                             "IDC Req Rcvd:%04x, mb1=%x mb2=%x mb3=%x",
2733                             code, mbox1, mbox2, mbox3);
2734 
2735                         /* check if "ACK" is required (timeout != 0) */
2736                         if (mbox1 & 0x0f00) {
2737                                 caddr_t req;
2738 
2739                                 /*
2740                                  * Ack the request (queue work to do it?)
2741                                  * using a mailbox iocb
2742                                  */
2743                                 mutex_enter(&qlt->req_lock);
2744                                 req = qlt_get_req_entries(qlt, 1);
2745                                 if (req) {
2746                                         bzero(req, IOCB_SIZE);
2747                                         req[0] = 0x39; req[1] = 1;
2748                                         QMEM_WR16(qlt, req+8, 0x101);
2749                                         QMEM_WR16(qlt, req+10, mbox1);
2750                                         QMEM_WR16(qlt, req+12, mbox2);
2751                                         QMEM_WR16(qlt, req+14, mbox3);
2752                                         QMEM_WR16(qlt, req+16, mbox4);
2753                                         QMEM_WR16(qlt, req+18, mbox5);
2754                                         QMEM_WR16(qlt, req+20, mbox6);
2755                                         qlt_submit_req_entries(qlt, 1);
2756                                 } else {
2757                                         (void) snprintf(info, sizeof (info),
2758                                             "IDC ACK failed");
2759                                 }
2760                                 mutex_exit(&qlt->req_lock);
2761                         }
2762                 }
2763         } else if ((intr_type == 0x10) || (intr_type == 0x11)) {
2764                 /* Handle mailbox completion */
2765                 mutex_enter(&qlt->mbox_lock);
2766                 if (qlt->mbox_io_state != MBOX_STATE_CMD_RUNNING) {
2767                         cmn_err(CE_WARN, "qlt(%d): mailbox completion received"
2768                             " when driver wasn't waiting for it %d",
2769                             qlt->instance, qlt->mbox_io_state);
2770                 } else {
2771                         for (i = 0; i < MAX_MBOXES; i++) {
2772                                 if (qlt->mcp->from_fw_mask &
2773                                     (((uint32_t)1) << i)) {
2774                                         qlt->mcp->from_fw[i] =
2775                                             REG_RD16(qlt, REG_MBOX(i));
2776                                 }
2777                         }
2778                         qlt->mbox_io_state = MBOX_STATE_CMD_DONE;
2779                 }
2780                 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2781                 cv_broadcast(&qlt->mbox_cv);
2782                 mutex_exit(&qlt->mbox_lock);
2783         } else {
2784                 cmn_err(CE_WARN, "qlt(%d): Unknown intr type 0x%x",
2785                     qlt->instance, intr_type);
2786                 REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
2787         }
2788 
2789         (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting */
2790         risc_status = REG_RD32(qlt, REG_RISC_STATUS);
2791         if ((risc_status & BIT_15) &&
2792             (++intr_loop_count < QLT_MAX_ITERATIONS_PER_INTR)) {
2793                 goto intr_again;
2794         }
2795 
2796         REG_WR32(qlt, REG_INTR_CTRL, ENABLE_RISC_INTR);
2797 
2798         mutex_exit(&qlt->intr_lock);
2799         return (DDI_INTR_CLAIMED);
2800 }
2801 
2802 /* **************** NVRAM Functions ********************** */
2803 
2804 fct_status_t
2805 qlt_read_flash_word(qlt_state_t *qlt, uint32_t faddr, uint32_t *bp)
2806 {
2807         uint32_t        timer;
2808 
2809         /* Clear access error flag */
2810         REG_WR32(qlt, REG_CTRL_STATUS,
2811             REG_RD32(qlt, REG_CTRL_STATUS) | FLASH_ERROR);
2812 
2813         REG_WR32(qlt, REG_FLASH_ADDR, faddr & ~BIT_31);
2814 
2815         /* Wait for READ cycle to complete. */
2816         for (timer = 3000; timer; timer--) {
2817                 if (REG_RD32(qlt, REG_FLASH_ADDR) & BIT_31) {
2818                         break;
2819                 }
2820                 drv_usecwait(10);
2821         }
2822         if (timer == 0) {
2823                 EL(qlt, "flash timeout\n");
2824                 return (QLT_FLASH_TIMEOUT);
2825         } else if (REG_RD32(qlt, REG_CTRL_STATUS) & FLASH_ERROR) {
2826                 EL(qlt, "flash access error\n");
2827                 return (QLT_FLASH_ACCESS_ERROR);
2828         }
2829 
2830         *bp = REG_RD32(qlt, REG_FLASH_DATA);
2831 
2832         return (QLT_SUCCESS);
2833 }
2834 
2835 fct_status_t
2836 qlt_read_nvram(qlt_state_t *qlt)
2837 {
2838         uint32_t                index, addr, chksum;
2839         uint32_t                val, *ptr;
2840         fct_status_t            ret;
2841         qlt_nvram_t             *nv;
2842         uint64_t                empty_node_name = 0;
2843 
2844         if (qlt->qlt_81xx_chip) {
2845                 addr = REG_RD32(qlt, REG_CTRL_STATUS) & BIT_12 ?
2846                     QLT81_NVRAM_FUNC1_ADDR : QLT81_NVRAM_FUNC0_ADDR;
2847         } else if (qlt->qlt_25xx_chip) {
2848                 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
2849                     QLT25_NVRAM_FUNC1_ADDR : QLT25_NVRAM_FUNC0_ADDR;
2850         } else {
2851                 addr = REG_RD32(qlt, REG_CTRL_STATUS) & FUNCTION_NUMBER ?
2852                     NVRAM_FUNC1_ADDR : NVRAM_FUNC0_ADDR;
2853         }
2854         mutex_enter(&qlt_global_lock);
2855 
2856         /* Pause RISC. */
2857         REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
2858         (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
2859 
2860         /* Get NVRAM data and calculate checksum. */
2861         ptr = (uint32_t *)qlt->nvram;
2862         chksum = 0;
2863         for (index = 0; index < sizeof (qlt_nvram_t) / 4; index++) {
2864                 ret = qlt_read_flash_word(qlt, addr++, &val);
2865                 if (ret != QLT_SUCCESS) {
2866                         EL(qlt, "qlt_read_flash_word, status=%llxh\n", ret);
2867                         mutex_exit(&qlt_global_lock);
2868                         return (ret);
2869                 }
2870                 chksum += val;
2871                 *ptr = LE_32(val);
2872                 ptr++;
2873         }
2874 
2875         /* Release RISC Pause */
2876         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_PAUSE));
2877         (void) REG_RD32(qlt, REG_HCCR); /* PCI Posting. */
2878 
2879         mutex_exit(&qlt_global_lock);
2880 
2881         /* Sanity check NVRAM Data */
2882         nv = qlt->nvram;
2883         if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
2884             nv->id[2] != 'P' || nv->id[3] != ' ' ||
2885             (nv->nvram_version[0] | nv->nvram_version[1]) == 0) {
2886                 EL(qlt, "chksum=%xh, id=%c%c%c%c, ver=%02d%02d\n", chksum,
2887                     nv->id[0], nv->id[1], nv->id[2], nv->id[3],
2888                     nv->nvram_version[1], nv->nvram_version[0]);
2889                 return (QLT_BAD_NVRAM_DATA);
2890         }
2891 
2892         /* If node name is zero, hand craft it from port name */
2893         if (bcmp(nv->node_name, &empty_node_name, 8) == 0) {
2894                 bcopy(nv->port_name, nv->node_name, 8);
2895                 nv->node_name[0] = (uint8_t)(nv->node_name[0] & ~BIT_0);
2896                 nv->port_name[0] = (uint8_t)(nv->node_name[0] | BIT_0);
2897         }
2898 
2899         return (QLT_SUCCESS);
2900 }
2901 
2902 uint32_t
2903 qlt_sync_atio_queue(qlt_state_t *qlt)
2904 {
2905         uint32_t total_ent;
2906 
2907         if (qlt->atio_ndx_from_fw > qlt->atio_ndx_to_fw) {
2908                 total_ent = qlt->atio_ndx_from_fw - qlt->atio_ndx_to_fw;
2909                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, ATIO_QUEUE_OFFSET
2910                     + (qlt->atio_ndx_to_fw << 6), total_ent << 6,
2911                     DDI_DMA_SYNC_FORCPU);
2912         } else {
2913                 total_ent = ATIO_QUEUE_ENTRIES - qlt->atio_ndx_to_fw +
2914                     qlt->atio_ndx_from_fw;
2915                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle, ATIO_QUEUE_OFFSET
2916                     + (qlt->atio_ndx_to_fw << 6), (uint_t)(ATIO_QUEUE_ENTRIES -
2917                     qlt->atio_ndx_to_fw) << 6, DDI_DMA_SYNC_FORCPU);
2918                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
2919                     ATIO_QUEUE_OFFSET, (uint_t)(qlt->atio_ndx_from_fw << 6),
2920                     DDI_DMA_SYNC_FORCPU);
2921         }
2922         return (total_ent);
2923 }
2924 
2925 void
2926 qlt_handle_atio_queue_update(qlt_state_t *qlt)
2927 {
2928         uint32_t total_ent;
2929 
2930         if (qlt->atio_ndx_to_fw == qlt->atio_ndx_from_fw)
2931                 return;
2932 
2933         total_ent = qlt_sync_atio_queue(qlt);
2934 
2935         do {
2936                 uint8_t *atio = (uint8_t *)&qlt->atio_ptr[
2937                     qlt->atio_ndx_to_fw << 6];
2938                 uint32_t ent_cnt;
2939 
2940                 ent_cnt = (uint32_t)(atio[1]);
2941                 if (ent_cnt > total_ent) {
2942                         break;
2943                 }
2944                 switch ((uint8_t)(atio[0])) {
2945                 case 0x0d:      /* INOT */
2946                         qlt_handle_inot(qlt, atio);
2947                         break;
2948                 case 0x06:      /* ATIO */
2949                         qlt_handle_atio(qlt, atio);
2950                         break;
2951                 default:
2952                         EL(qlt, "atio_queue_update atio[0]=%xh\n", atio[0]);
2953                         cmn_err(CE_WARN, "qlt_handle_atio_queue_update: "
2954                             "atio[0] is %x, qlt-%p", atio[0], (void *)qlt);
2955                         break;
2956                 }
2957                 qlt->atio_ndx_to_fw = (uint16_t)(
2958                     (qlt->atio_ndx_to_fw + ent_cnt) & (ATIO_QUEUE_ENTRIES - 1));
2959                 total_ent -= ent_cnt;
2960         } while (total_ent > 0);
2961         REG_WR32(qlt, REG_ATIO_OUT_PTR, qlt->atio_ndx_to_fw);
2962 }
2963 
2964 uint32_t
2965 qlt_sync_resp_queue(qlt_state_t *qlt)
2966 {
2967         uint32_t total_ent;
2968 
2969         if (qlt->resp_ndx_from_fw > qlt->resp_ndx_to_fw) {
2970                 total_ent = qlt->resp_ndx_from_fw - qlt->resp_ndx_to_fw;
2971                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
2972                     RESPONSE_QUEUE_OFFSET
2973                     + (qlt->resp_ndx_to_fw << 6), total_ent << 6,
2974                     DDI_DMA_SYNC_FORCPU);
2975         } else {
2976                 total_ent = RESPONSE_QUEUE_ENTRIES - qlt->resp_ndx_to_fw +
2977                     qlt->resp_ndx_from_fw;
2978                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
2979                     RESPONSE_QUEUE_OFFSET
2980                     + (qlt->resp_ndx_to_fw << 6), (RESPONSE_QUEUE_ENTRIES -
2981                     qlt->resp_ndx_to_fw) << 6, DDI_DMA_SYNC_FORCPU);
2982                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
2983                     RESPONSE_QUEUE_OFFSET,
2984                     qlt->resp_ndx_from_fw << 6, DDI_DMA_SYNC_FORCPU);
2985         }
2986         return (total_ent);
2987 }
2988 
2989 void
2990 qlt_handle_resp_queue_update(qlt_state_t *qlt)
2991 {
2992         uint32_t total_ent;
2993         uint8_t c;
2994 
2995         if (qlt->resp_ndx_to_fw == qlt->resp_ndx_from_fw)
2996                 return;
2997 
2998         total_ent = qlt_sync_resp_queue(qlt);
2999 
3000         do {
3001                 caddr_t resp = &qlt->resp_ptr[qlt->resp_ndx_to_fw << 6];
3002                 uint32_t ent_cnt;
3003 
3004                 ent_cnt = (uint32_t)(resp[0] == 0x51 ? resp[1] : 1);
3005                 if (ent_cnt > total_ent) {
3006                         break;
3007                 }
3008                 switch ((uint8_t)(resp[0])) {
3009                 case 0x12:      /* CTIO completion */
3010                         qlt_handle_ctio_completion(qlt, (uint8_t *)resp);
3011                         break;
3012                 case 0x0e:      /* NACK */
3013                         /* Do Nothing */
3014                         break;
3015                 case 0x1b:      /* Verify FW */
3016                         qlt_handle_verify_fw_completion(qlt, (uint8_t *)resp);
3017                         break;
3018                 case 0x29:      /* CT PassThrough */
3019                         qlt_handle_ct_completion(qlt, (uint8_t *)resp);
3020                         break;
3021                 case 0x33:      /* Abort IO IOCB completion */
3022                         qlt_handle_sol_abort_completion(qlt, (uint8_t *)resp);
3023                         break;
3024                 case 0x51:      /* PUREX */
3025                         qlt_handle_purex(qlt, (uint8_t *)resp);
3026                         break;
3027                 case 0x52:
3028                         qlt_handle_dereg_completion(qlt, (uint8_t *)resp);
3029                         break;
3030                 case 0x53:      /* ELS passthrough */
3031                         c = (uint8_t)(((uint8_t)resp[0x1f]) >> 5);
3032                         if (c == 0) {
3033                                 qlt_handle_sol_els_completion(qlt,
3034                                     (uint8_t *)resp);
3035                         } else if (c == 3) {
3036                                 qlt_handle_unsol_els_abort_completion(qlt,
3037                                     (uint8_t *)resp);
3038                         } else {
3039                                 qlt_handle_unsol_els_completion(qlt,
3040                                     (uint8_t *)resp);
3041                         }
3042                         break;
3043                 case 0x54:      /* ABTS received */
3044                         qlt_handle_rcvd_abts(qlt, (uint8_t *)resp);
3045                         break;
3046                 case 0x55:      /* ABTS completion */
3047                         qlt_handle_abts_completion(qlt, (uint8_t *)resp);
3048                         break;
3049                 default:
3050                         EL(qlt, "response entry=%xh\n", resp[0]);
3051                         break;
3052                 }
3053                 qlt->resp_ndx_to_fw = (qlt->resp_ndx_to_fw + ent_cnt) &
3054                     (RESPONSE_QUEUE_ENTRIES - 1);
3055                 total_ent -= ent_cnt;
3056         } while (total_ent > 0);
3057         REG_WR32(qlt, REG_RESP_OUT_PTR, qlt->resp_ndx_to_fw);
3058 }
3059 
3060 fct_status_t
3061 qlt_portid_to_handle(qlt_state_t *qlt, uint32_t id, uint16_t cmd_handle,
3062                                 uint16_t *ret_handle)
3063 {
3064         fct_status_t ret;
3065         mbox_cmd_t *mcp;
3066         uint16_t n;
3067         uint16_t h;
3068         uint32_t ent_id;
3069         uint8_t *p;
3070         int found = 0;
3071 
3072         mcp = qlt_alloc_mailbox_command(qlt, 2048 * 8);
3073         if (mcp == NULL) {
3074                 return (STMF_ALLOC_FAILURE);
3075         }
3076         mcp->to_fw[0] = MBC_GET_ID_LIST;
3077         mcp->to_fw[8] = 2048 * 8;
3078         mcp->to_fw[9] = 0;
3079         mcp->to_fw_mask |= BIT_9 | BIT_8;
3080         mcp->from_fw_mask |= BIT_1 | BIT_2;
3081 
3082         ret = qlt_mailbox_command(qlt, mcp);
3083         if (ret != QLT_SUCCESS) {
3084                 EL(qlt, "qlt_mailbox_command=7Ch status=%llxh\n", ret);
3085                 cmn_err(CE_WARN, "GET ID list failed, ret = %llx, mb0=%x, "
3086                     "mb1=%x, mb2=%x", (long long)ret, mcp->from_fw[0],
3087                     mcp->from_fw[1], mcp->from_fw[2]);
3088                 qlt_free_mailbox_command(qlt, mcp);
3089                 return (ret);
3090         }
3091         qlt_dmem_dma_sync(mcp->dbuf, DDI_DMA_SYNC_FORCPU);
3092         p = mcp->dbuf->db_sglist[0].seg_addr;
3093         for (n = 0; n < mcp->from_fw[1]; n++) {
3094                 ent_id = LE_32(*((uint32_t *)p)) & 0xFFFFFF;
3095                 h = (uint16_t)((uint16_t)p[4] | (((uint16_t)p[5]) << 8));
3096                 if (ent_id == id) {
3097                         found = 1;
3098                         *ret_handle = h;
3099                         if ((cmd_handle != FCT_HANDLE_NONE) &&
3100                             (cmd_handle != h)) {
3101                                 cmn_err(CE_WARN, "login for portid %x came in "
3102                                     "with handle %x, while the portid was "
3103                                     "already using a different handle %x",
3104                                     id, cmd_handle, h);
3105                                 qlt_free_mailbox_command(qlt, mcp);
3106                                 return (QLT_FAILURE);
3107                         }
3108                         break;
3109                 }
3110                 if ((cmd_handle != FCT_HANDLE_NONE) && (h == cmd_handle)) {
3111                         cmn_err(CE_WARN, "login for portid %x came in with "
3112                             "handle %x, while the handle was already in use "
3113                             "for portid %x", id, cmd_handle, ent_id);
3114                         qlt_free_mailbox_command(qlt, mcp);
3115                         return (QLT_FAILURE);
3116                 }
3117                 p += 8;
3118         }
3119         if (!found) {
3120                 *ret_handle = cmd_handle;
3121         }
3122         qlt_free_mailbox_command(qlt, mcp);
3123         return (FCT_SUCCESS);
3124 }
3125 
3126 /* ARGSUSED */
3127 fct_status_t
3128 qlt_fill_plogi_req(fct_local_port_t *port, fct_remote_port_t *rp,
3129                                 fct_cmd_t *login)
3130 {
3131         uint8_t *p;
3132 
3133         p = ((fct_els_t *)login->cmd_specific)->els_req_payload;
3134         p[0] = ELS_OP_PLOGI;
3135         *((uint16_t *)(&p[4])) = 0x2020;
3136         p[7] = 3;
3137         p[8] = 0x88;
3138         p[10] = 8;
3139         p[13] = 0xff; p[15] = 0x1f;
3140         p[18] = 7; p[19] = 0xd0;
3141 
3142         bcopy(port->port_pwwn, p + 20, 8);
3143         bcopy(port->port_nwwn, p + 28, 8);
3144 
3145         p[68] = 0x80;
3146         p[74] = 8;
3147         p[77] = 0xff;
3148         p[81] = 1;
3149 
3150         return (FCT_SUCCESS);
3151 }
3152 
3153 /* ARGSUSED */
3154 fct_status_t
3155 qlt_fill_plogi_resp(fct_local_port_t *port, fct_remote_port_t *rp,
3156                                 fct_cmd_t *login)
3157 {
3158         return (FCT_SUCCESS);
3159 }
3160 
3161 fct_status_t
3162 qlt_register_remote_port(fct_local_port_t *port, fct_remote_port_t *rp,
3163     fct_cmd_t *login)
3164 {
3165         uint16_t h;
3166         fct_status_t ret;
3167         qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
3168 
3169         switch (rp->rp_id) {
3170         case 0xFFFFFC:  h = 0x7FC; break;
3171         case 0xFFFFFD:  h = 0x7FD; break;
3172         case 0xFFFFFE:  h = 0x7FE; break;
3173         case 0xFFFFFF:  h = 0x7FF; break;
3174         default:
3175                 ret = qlt_portid_to_handle(qlt, rp->rp_id,
3176                     login->cmd_rp_handle, &h);
3177                 if (ret != FCT_SUCCESS) {
3178                         EL(qlt, "qlt_portid_to_handle, status=%llxh\n", ret);
3179                         return (ret);
3180                 }
3181         }
3182 
3183         if (login->cmd_type == FCT_CMD_SOL_ELS) {
3184                 ret = qlt_fill_plogi_req(port, rp, login);
3185         } else {
3186                 ret = qlt_fill_plogi_resp(port, rp, login);
3187         }
3188 
3189         if (ret != FCT_SUCCESS) {
3190                 EL(qlt, "qlt_fill_plogi, status=%llxh\n", ret);
3191                 return (ret);
3192         }
3193 
3194         if (h == FCT_HANDLE_NONE)
3195                 return (FCT_SUCCESS);
3196 
3197         if (rp->rp_handle == FCT_HANDLE_NONE) {
3198                 rp->rp_handle = h;
3199                 return (FCT_SUCCESS);
3200         }
3201 
3202         if (rp->rp_handle == h)
3203                 return (FCT_SUCCESS);
3204 
3205         EL(qlt, "rp_handle=%xh != h=%xh\n", rp->rp_handle, h);
3206         return (FCT_FAILURE);
3207 }
3208 /* invoked in single thread */
3209 fct_status_t
3210 qlt_deregister_remote_port(fct_local_port_t *port, fct_remote_port_t *rp)
3211 {
3212         uint8_t *req;
3213         qlt_state_t *qlt;
3214         clock_t dereg_req_timer;
3215         fct_status_t ret;
3216 
3217         qlt = (qlt_state_t *)port->port_fca_private;
3218 
3219         if ((qlt->qlt_state == FCT_STATE_OFFLINE) ||
3220             (qlt->qlt_state == FCT_STATE_OFFLINING))
3221                 return (FCT_SUCCESS);
3222         ASSERT(qlt->rp_id_in_dereg == 0);
3223 
3224         mutex_enter(&qlt->preq_lock);
3225         req = (uint8_t *)qlt_get_preq_entries(qlt, 1);
3226         if (req == NULL) {
3227                 mutex_exit(&qlt->preq_lock);
3228                 return (FCT_BUSY);
3229         }
3230         bzero(req, IOCB_SIZE);
3231         req[0] = 0x52; req[1] = 1;
3232         /* QMEM_WR32(qlt, (&req[4]), 0xffffffff);  */
3233         QMEM_WR16(qlt, (&req[0xA]), rp->rp_handle);
3234         QMEM_WR16(qlt, (&req[0xC]), 0x98); /* implicit logo */
3235         QMEM_WR32(qlt, (&req[0x10]), rp->rp_id);
3236         qlt->rp_id_in_dereg = rp->rp_id;
3237         qlt_submit_preq_entries(qlt, 1);
3238 
3239         dereg_req_timer = ddi_get_lbolt() + drv_usectohz(DEREG_RP_TIMEOUT);
3240         if (cv_timedwait(&qlt->rp_dereg_cv,
3241             &qlt->preq_lock, dereg_req_timer) > 0) {
3242                 ret = qlt->rp_dereg_status;
3243         } else {
3244                 ret = FCT_BUSY;
3245         }
3246         qlt->rp_dereg_status = 0;
3247         qlt->rp_id_in_dereg = 0;
3248         mutex_exit(&qlt->preq_lock);
3249         return (ret);
3250 }
3251 
3252 /*
3253  * Pass received ELS up to framework.
3254  */
3255 static void
3256 qlt_handle_purex(qlt_state_t *qlt, uint8_t *resp)
3257 {
3258         fct_cmd_t               *cmd;
3259         fct_els_t               *els;
3260         qlt_cmd_t               *qcmd;
3261         uint32_t                payload_size;
3262         uint32_t                remote_portid;
3263         uint8_t                 *pldptr, *bndrptr;
3264         int                     i, off;
3265         uint16_t                iocb_flags;
3266         char                    info[QLT_INFO_LEN];
3267 
3268         remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
3269             ((uint32_t)(resp[0x1A])) << 16;
3270         iocb_flags = QMEM_RD16(qlt, (&resp[8]));
3271         if (iocb_flags & BIT_15) {
3272                 payload_size = (QMEM_RD16(qlt, (&resp[0x0e])) & 0xfff) - 24;
3273         } else {
3274                 payload_size = QMEM_RD16(qlt, (&resp[0x0c])) - 24;
3275         }
3276 
3277         if (payload_size > ((uint32_t)resp[1] * IOCB_SIZE - 0x2C)) {
3278                 EL(qlt, "payload is too large = %xh\n", payload_size);
3279                 cmn_err(CE_WARN, "handle_purex: payload is too large");
3280                 goto cmd_null;
3281         }
3282 
3283         cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ELS,
3284             (int)(payload_size + GET_STRUCT_SIZE(qlt_cmd_t)), 0);
3285         if (cmd == NULL) {
3286                 EL(qlt, "fct_alloc cmd==NULL\n");
3287 cmd_null:;
3288                 (void) snprintf(info, sizeof (info),
3289                     "qlt_handle_purex: qlt-%p, "
3290                     "can't allocate space for fct_cmd", (void *)qlt);
3291                 (void) fct_port_shutdown(qlt->qlt_port,
3292                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
3293                 return;
3294         }
3295 
3296         cmd->cmd_port = qlt->qlt_port;
3297         cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xa);
3298         if (cmd->cmd_rp_handle == 0xFFFF) {
3299                 cmd->cmd_rp_handle = FCT_HANDLE_NONE;
3300         }
3301 
3302         els = (fct_els_t *)cmd->cmd_specific;
3303         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
3304         els->els_req_size = (uint16_t)payload_size;
3305         els->els_req_payload = GET_BYTE_OFFSET(qcmd,
3306             GET_STRUCT_SIZE(qlt_cmd_t));
3307         qcmd->fw_xchg_addr = QMEM_RD32(qlt, (&resp[0x10]));
3308         cmd->cmd_rportid = remote_portid;
3309         cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
3310             ((uint32_t)(resp[0x16])) << 16;
3311         cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
3312         cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
3313         pldptr = &resp[0x2C];
3314         bndrptr = (uint8_t *)(qlt->resp_ptr + (RESPONSE_QUEUE_ENTRIES << 6));
3315         for (i = 0, off = 0x2c; i < payload_size; i += 4) {
3316                 /* Take care of fw's swapping of payload */
3317                 els->els_req_payload[i] = pldptr[3];
3318                 els->els_req_payload[i+1] = pldptr[2];
3319                 els->els_req_payload[i+2] = pldptr[1];
3320                 els->els_req_payload[i+3] = pldptr[0];
3321                 pldptr += 4;
3322                 if (pldptr == bndrptr)
3323                         pldptr = (uint8_t *)qlt->resp_ptr;
3324                 off += 4;
3325                 if (off >= IOCB_SIZE) {
3326                         off = 4;
3327                         pldptr += 4;
3328                 }
3329         }
3330         fct_post_rcvd_cmd(cmd, 0);
3331 }
3332 
3333 fct_status_t
3334 qlt_send_cmd_response(fct_cmd_t *cmd, uint32_t ioflags)
3335 {
3336         qlt_state_t     *qlt;
3337         char            info[QLT_INFO_LEN];
3338 
3339         qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
3340 
3341         if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
3342                 if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
3343                         EL(qlt, "ioflags = %xh\n", ioflags);
3344                         goto fatal_panic;
3345                 } else {
3346                         return (qlt_send_status(qlt, cmd));
3347                 }
3348         }
3349 
3350         if (cmd->cmd_type == FCT_CMD_RCVD_ELS) {
3351                 if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
3352                         goto fatal_panic;
3353                 } else {
3354                         return (qlt_send_els_response(qlt, cmd));
3355                 }
3356         }
3357 
3358         if (ioflags & FCT_IOF_FORCE_FCA_DONE) {
3359                 cmd->cmd_handle = 0;
3360         }
3361 
3362         if (cmd->cmd_type == FCT_CMD_RCVD_ABTS) {
3363                 return (qlt_send_abts_response(qlt, cmd, 0));
3364         } else {
3365                 EL(qlt, "cmd->cmd_type=%xh\n", cmd->cmd_type);
3366                 ASSERT(0);
3367                 return (FCT_FAILURE);
3368         }
3369 
3370 fatal_panic:;
3371         (void) snprintf(info, sizeof (info),
3372             "qlt_send_cmd_response: can not handle "
3373             "FCT_IOF_FORCE_FCA_DONE for cmd %p, ioflags-%x", (void *)cmd,
3374             ioflags);
3375         (void) fct_port_shutdown(qlt->qlt_port,
3376             STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
3377         return (FCT_FAILURE);
3378 }
3379 
3380 /* ARGSUSED */
3381 fct_status_t
3382 qlt_xfer_scsi_data(fct_cmd_t *cmd, stmf_data_buf_t *dbuf, uint32_t ioflags)
3383 {
3384         qlt_dmem_bctl_t *bctl = (qlt_dmem_bctl_t *)dbuf->db_port_private;
3385         qlt_state_t     *qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
3386         qlt_cmd_t       *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
3387         uint8_t         *req, rcnt;
3388         uint16_t        flags;
3389         uint16_t        cookie_count;
3390 
3391         if (dbuf->db_handle == 0)
3392                 qcmd->dbuf = dbuf;
3393         flags = (uint16_t)(((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5);
3394         if (dbuf->db_flags & DB_DIRECTION_TO_RPORT) {
3395                 flags = (uint16_t)(flags | 2);
3396                 qlt_dmem_dma_sync(dbuf, DDI_DMA_SYNC_FORDEV);
3397         } else {
3398                 flags = (uint16_t)(flags | 1);
3399         }
3400 
3401         if (dbuf->db_flags & DB_SEND_STATUS_GOOD)
3402                 flags = (uint16_t)(flags | BIT_15);
3403 
3404         if (dbuf->db_flags & DB_LU_DATA_BUF) {
3405                 /*
3406                  * Data bufs from LU are in scatter/gather list format.
3407                  */
3408                 cookie_count = qlt_get_cookie_count(dbuf);
3409                 rcnt = qlt_get_iocb_count(cookie_count);
3410         } else {
3411                 cookie_count = 1;
3412                 rcnt = 1;
3413         }
3414         mutex_enter(&qlt->req_lock);
3415         req = (uint8_t *)qlt_get_req_entries(qlt, rcnt);
3416         if (req == NULL) {
3417                 mutex_exit(&qlt->req_lock);
3418                 return (FCT_BUSY);
3419         }
3420         bzero(req, IOCB_SIZE);  /* XXX needed ? */
3421         req[0] = 0x12;
3422         req[1] = rcnt;
3423         req[2] = dbuf->db_handle;
3424         QMEM_WR32(qlt, req+4, cmd->cmd_handle);
3425         QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle);
3426         QMEM_WR16(qlt, req+10, 60);     /* 60 seconds timeout */
3427         QMEM_WR16(qlt, req+12, cookie_count);
3428         QMEM_WR32(qlt, req+0x10, cmd->cmd_rportid);
3429         QMEM_WR32(qlt, req+0x14, qcmd->fw_xchg_addr);
3430         QMEM_WR16(qlt, req+0x1A, flags);
3431         QMEM_WR16(qlt, req+0x20, cmd->cmd_oxid);
3432         QMEM_WR32(qlt, req+0x24, dbuf->db_relative_offset);
3433         QMEM_WR32(qlt, req+0x2C, dbuf->db_data_size);
3434         if (dbuf->db_flags & DB_LU_DATA_BUF) {
3435                 uint8_t                 *qptr;  /* qlt continuation segs */
3436                 uint16_t                cookie_resid;
3437                 uint16_t                cont_segs;
3438                 ddi_dma_cookie_t        cookie, *ckp;
3439 
3440                 /*
3441                  * See if the dma cookies are in simple array format.
3442                  */
3443                 ckp = qlt_get_cookie_array(dbuf);
3444 
3445                 /*
3446                  * Program the first segment into main record.
3447                  */
3448                 if (ckp) {
3449                         ASSERT(ckp->dmac_size);
3450                         QMEM_WR64(qlt, req+0x34, ckp->dmac_laddress);
3451                         QMEM_WR32(qlt, req+0x3c, ckp->dmac_size);
3452                 } else {
3453                         qlt_ddi_dma_nextcookie(dbuf, &cookie);
3454                         ASSERT(cookie.dmac_size);
3455                         QMEM_WR64(qlt, req+0x34, cookie.dmac_laddress);
3456                         QMEM_WR32(qlt, req+0x3c, cookie.dmac_size);
3457                 }
3458                 cookie_resid = cookie_count-1;
3459 
3460                 /*
3461                  * Program remaining segments into continuation records.
3462                  */
3463                 while (cookie_resid) {
3464                         req += IOCB_SIZE;
3465                         if (req >= (uint8_t *)qlt->resp_ptr) {
3466                                 req = (uint8_t *)qlt->req_ptr;
3467                         }
3468                         req[0] = 0x0a;
3469                         req[1] = 1;
3470                         req[2] = req[3] = 0;    /* tidy */
3471                         qptr = &req[4];
3472                         for (cont_segs = CONT_A64_DATA_SEGMENTS;
3473                             cont_segs && cookie_resid; cont_segs--) {
3474 
3475                                 if (ckp) {
3476                                         ++ckp;          /* next cookie */
3477                                         ASSERT(ckp->dmac_size != 0);
3478                                         QMEM_WR64(qlt, qptr,
3479                                             ckp->dmac_laddress);
3480                                         qptr += 8;      /* skip over laddress */
3481                                         QMEM_WR32(qlt, qptr, ckp->dmac_size);
3482                                         qptr += 4;      /* skip over size */
3483                                 } else {
3484                                         qlt_ddi_dma_nextcookie(dbuf, &cookie);
3485                                         ASSERT(cookie.dmac_size != 0);
3486                                         QMEM_WR64(qlt, qptr,
3487                                             cookie.dmac_laddress);
3488                                         qptr += 8;      /* skip over laddress */
3489                                         QMEM_WR32(qlt, qptr, cookie.dmac_size);
3490                                         qptr += 4;      /* skip over size */
3491                                 }
3492                                 cookie_resid--;
3493                         }
3494                         /*
3495                          * zero unused remainder of IOCB
3496                          */
3497                         if (cont_segs) {
3498                                 size_t resid;
3499                                 resid = (size_t)((uintptr_t)(req+IOCB_SIZE) -
3500                                     (uintptr_t)qptr);
3501                                 ASSERT(resid < IOCB_SIZE);
3502                                 bzero(qptr, resid);
3503                         }
3504                 }
3505         } else {
3506                 /* Single, contiguous buffer */
3507                 QMEM_WR64(qlt, req+0x34, bctl->bctl_dev_addr);
3508                 QMEM_WR32(qlt, req+0x34+8, dbuf->db_data_size);
3509         }
3510 
3511         qlt_submit_req_entries(qlt, rcnt);
3512         mutex_exit(&qlt->req_lock);
3513 
3514         return (STMF_SUCCESS);
3515 }
3516 
3517 /*
3518  * We must construct proper FCP_RSP_IU now. Here we only focus on
3519  * the handling of FCP_SNS_INFO. If there's protocol failures (FCP_RSP_INFO),
3520  * we could have catched them before we enter here.
3521  */
3522 fct_status_t
3523 qlt_send_status(qlt_state_t *qlt, fct_cmd_t *cmd)
3524 {
3525         qlt_cmd_t *qcmd         = (qlt_cmd_t *)cmd->cmd_fca_private;
3526         scsi_task_t *task       = (scsi_task_t *)cmd->cmd_specific;
3527         qlt_dmem_bctl_t *bctl;
3528         uint32_t size;
3529         uint8_t *req, *fcp_rsp_iu;
3530         uint8_t *psd, sensbuf[24];              /* sense data */
3531         uint16_t flags;
3532         uint16_t scsi_status;
3533         int use_mode2;
3534         int ndx;
3535 
3536         /*
3537          * Enter fast channel for non check condition
3538          */
3539         if (task->task_scsi_status != STATUS_CHECK) {
3540                 /*
3541                  * We will use mode1
3542                  */
3543                 flags = (uint16_t)(BIT_6 | BIT_15 |
3544                     (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
3545                 scsi_status = (uint16_t)task->task_scsi_status;
3546                 if (task->task_status_ctrl == TASK_SCTRL_OVER) {
3547                         scsi_status = (uint16_t)(scsi_status | BIT_10);
3548                 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
3549                         scsi_status = (uint16_t)(scsi_status | BIT_11);
3550                 }
3551                 qcmd->dbuf_rsp_iu = NULL;
3552 
3553                 /*
3554                  * Fillout CTIO type 7 IOCB
3555                  */
3556                 mutex_enter(&qlt->req_lock);
3557                 req = (uint8_t *)qlt_get_req_entries(qlt, 1);
3558                 if (req == NULL) {
3559                         mutex_exit(&qlt->req_lock);
3560                         return (FCT_BUSY);
3561                 }
3562 
3563                 /*
3564                  * Common fields
3565                  */
3566                 bzero(req, IOCB_SIZE);
3567                 req[0x00] = 0x12;
3568                 req[0x01] = 0x1;
3569                 req[0x02] = BIT_7;      /* indicate if it's a pure status req */
3570                 QMEM_WR32(qlt, req + 0x04, cmd->cmd_handle);
3571                 QMEM_WR16(qlt, req + 0x08, cmd->cmd_rp->rp_handle);
3572                 QMEM_WR32(qlt, req + 0x10, cmd->cmd_rportid);
3573                 QMEM_WR32(qlt, req + 0x14, qcmd->fw_xchg_addr);
3574 
3575                 /*
3576                  * Mode-specific fields
3577                  */
3578                 QMEM_WR16(qlt, req + 0x1A, flags);
3579                 QMEM_WR32(qlt, req + 0x1C, task->task_resid);
3580                 QMEM_WR16(qlt, req + 0x20, cmd->cmd_oxid);
3581                 QMEM_WR16(qlt, req + 0x22, scsi_status);
3582 
3583                 /*
3584                  * Trigger FW to send SCSI status out
3585                  */
3586                 qlt_submit_req_entries(qlt, 1);
3587                 mutex_exit(&qlt->req_lock);
3588                 return (STMF_SUCCESS);
3589         }
3590 
3591         ASSERT(task->task_scsi_status == STATUS_CHECK);
3592         /*
3593          * Decide the SCSI status mode, that should be used
3594          */
3595         use_mode2 = (task->task_sense_length > 24);
3596 
3597         /*
3598          * Prepare required information per the SCSI status mode
3599          */
3600         flags = (uint16_t)(BIT_15 |
3601             (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
3602         if (use_mode2) {
3603                 flags = (uint16_t)(flags | BIT_7);
3604 
3605                 size = task->task_sense_length;
3606                 qcmd->dbuf_rsp_iu = qlt_i_dmem_alloc(qlt,
3607                     task->task_sense_length, &size, 0);
3608                 if (!qcmd->dbuf_rsp_iu) {
3609                         return (FCT_ALLOC_FAILURE);
3610                 }
3611 
3612                 /*
3613                  * Start to construct FCP_RSP IU
3614                  */
3615                 fcp_rsp_iu = qcmd->dbuf_rsp_iu->db_sglist[0].seg_addr;
3616                 bzero(fcp_rsp_iu, 24);
3617 
3618                 /*
3619                  * FCP_RSP IU flags, byte10
3620                  */
3621                 fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_1);
3622                 if (task->task_status_ctrl == TASK_SCTRL_OVER) {
3623                         fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_2);
3624                 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
3625                         fcp_rsp_iu[10] = (uint8_t)(fcp_rsp_iu[10] | BIT_3);
3626                 }
3627 
3628                 /*
3629                  * SCSI status code, byte11
3630                  */
3631                 fcp_rsp_iu[11] = task->task_scsi_status;
3632 
3633                 /*
3634                  * FCP_RESID (Overrun or underrun)
3635                  */
3636                 fcp_rsp_iu[12] = (uint8_t)((task->task_resid >> 24) & 0xFF);
3637                 fcp_rsp_iu[13] = (uint8_t)((task->task_resid >> 16) & 0xFF);
3638                 fcp_rsp_iu[14] = (uint8_t)((task->task_resid >>  8) & 0xFF);
3639                 fcp_rsp_iu[15] = (uint8_t)((task->task_resid >>  0) & 0xFF);
3640 
3641                 /*
3642                  * FCP_SNS_LEN
3643                  */
3644                 fcp_rsp_iu[18] = (uint8_t)((task->task_sense_length >> 8) &
3645                     0xFF);
3646                 fcp_rsp_iu[19] = (uint8_t)((task->task_sense_length >> 0) &
3647                     0xFF);
3648 
3649                 /*
3650                  * FCP_RSP_LEN
3651                  */
3652                 /*
3653                  * no FCP_RSP_INFO
3654                  */
3655                 /*
3656                  * FCP_SNS_INFO
3657                  */
3658                 bcopy(task->task_sense_data, fcp_rsp_iu + 24,
3659                     task->task_sense_length);
3660 
3661                 /*
3662                  * Ensure dma data consistency
3663                  */
3664                 qlt_dmem_dma_sync(qcmd->dbuf_rsp_iu, DDI_DMA_SYNC_FORDEV);
3665         } else {
3666                 flags = (uint16_t)(flags | BIT_6);
3667 
3668                 scsi_status = (uint16_t)task->task_scsi_status;
3669                 if (task->task_status_ctrl == TASK_SCTRL_OVER) {
3670                         scsi_status = (uint16_t)(scsi_status | BIT_10);
3671                 } else if (task->task_status_ctrl == TASK_SCTRL_UNDER) {
3672                         scsi_status = (uint16_t)(scsi_status | BIT_11);
3673                 }
3674                 if (task->task_sense_length) {
3675                         scsi_status = (uint16_t)(scsi_status | BIT_9);
3676                 }
3677                 bcopy(task->task_sense_data, sensbuf, task->task_sense_length);
3678                 qcmd->dbuf_rsp_iu = NULL;
3679         }
3680 
3681         /*
3682          * Fillout CTIO type 7 IOCB
3683          */
3684         mutex_enter(&qlt->req_lock);
3685         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
3686         if (req == NULL) {
3687                 mutex_exit(&qlt->req_lock);
3688                 if (use_mode2) {
3689                         qlt_dmem_free(cmd->cmd_port->port_fds,
3690                             qcmd->dbuf_rsp_iu);
3691                         qcmd->dbuf_rsp_iu = NULL;
3692                 }
3693                 return (FCT_BUSY);
3694         }
3695 
3696         /*
3697          * Common fields
3698          */
3699         bzero(req, IOCB_SIZE);
3700         req[0x00] = 0x12;
3701         req[0x01] = 0x1;
3702         req[0x02] = BIT_7;      /* to indicate if it's a pure status req */
3703         QMEM_WR32(qlt, req + 0x04, cmd->cmd_handle);
3704         QMEM_WR16(qlt, req + 0x08, cmd->cmd_rp->rp_handle);
3705         QMEM_WR16(qlt, req + 0x0A, 0);  /* not timed by FW */
3706         if (use_mode2) {
3707                 QMEM_WR16(qlt, req+0x0C, 1);    /* FCP RSP IU data field */
3708         }
3709         QMEM_WR32(qlt, req + 0x10, cmd->cmd_rportid);
3710         QMEM_WR32(qlt, req + 0x14, qcmd->fw_xchg_addr);
3711 
3712         /*
3713          * Mode-specific fields
3714          */
3715         if (!use_mode2) {
3716                 QMEM_WR16(qlt, req + 0x18, task->task_sense_length);
3717         }
3718         QMEM_WR16(qlt, req + 0x1A, flags);
3719         QMEM_WR32(qlt, req + 0x1C, task->task_resid);
3720         QMEM_WR16(qlt, req + 0x20, cmd->cmd_oxid);
3721         if (use_mode2) {
3722                 bctl = (qlt_dmem_bctl_t *)qcmd->dbuf_rsp_iu->db_port_private;
3723                 QMEM_WR32(qlt, req + 0x2C, 24 + task->task_sense_length);
3724                 QMEM_WR64(qlt, req + 0x34, bctl->bctl_dev_addr);
3725                 QMEM_WR32(qlt, req + 0x3C, 24 + task->task_sense_length);
3726         } else {
3727                 QMEM_WR16(qlt, req + 0x22, scsi_status);
3728                 psd = req+0x28;
3729 
3730                 /*
3731                  * Data in sense buf is always big-endian, data in IOCB
3732                  * should always be little-endian, so we must do swapping.
3733                  */
3734                 size = ((task->task_sense_length + 3) & (~3));
3735                 for (ndx = 0; ndx < size; ndx += 4) {
3736                         psd[ndx + 0] = sensbuf[ndx + 3];
3737                         psd[ndx + 1] = sensbuf[ndx + 2];
3738                         psd[ndx + 2] = sensbuf[ndx + 1];
3739                         psd[ndx + 3] = sensbuf[ndx + 0];
3740                 }
3741         }
3742 
3743         /*
3744          * Trigger FW to send SCSI status out
3745          */
3746         qlt_submit_req_entries(qlt, 1);
3747         mutex_exit(&qlt->req_lock);
3748 
3749         return (STMF_SUCCESS);
3750 }
3751 
3752 fct_status_t
3753 qlt_send_els_response(qlt_state_t *qlt, fct_cmd_t *cmd)
3754 {
3755         qlt_cmd_t       *qcmd;
3756         fct_els_t *els = (fct_els_t *)cmd->cmd_specific;
3757         uint8_t *req, *addr;
3758         qlt_dmem_bctl_t *bctl;
3759         uint32_t minsize;
3760         uint8_t elsop, req1f;
3761 
3762         addr = els->els_resp_payload;
3763         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
3764 
3765         minsize = els->els_resp_size;
3766         qcmd->dbuf = qlt_i_dmem_alloc(qlt, els->els_resp_size, &minsize, 0);
3767         if (qcmd->dbuf == NULL)
3768                 return (FCT_BUSY);
3769 
3770         bctl = (qlt_dmem_bctl_t *)qcmd->dbuf->db_port_private;
3771 
3772         bcopy(addr, qcmd->dbuf->db_sglist[0].seg_addr, els->els_resp_size);
3773         qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORDEV);
3774 
3775         if (addr[0] == 0x02) {  /* ACC */
3776                 req1f = BIT_5;
3777         } else {
3778                 req1f = BIT_6;
3779         }
3780         elsop = els->els_req_payload[0];
3781         if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
3782             (elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
3783                 req1f = (uint8_t)(req1f | BIT_4);
3784         }
3785 
3786         mutex_enter(&qlt->req_lock);
3787         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
3788         if (req == NULL) {
3789                 mutex_exit(&qlt->req_lock);
3790                 qlt_dmem_free(NULL, qcmd->dbuf);
3791                 qcmd->dbuf = NULL;
3792                 return (FCT_BUSY);
3793         }
3794         bzero(req, IOCB_SIZE);
3795         req[0] = 0x53; req[1] = 1; req[0xf] = 0x10;
3796         req[0x16] = elsop; req[0x1f] = req1f;
3797         QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
3798         QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
3799         QMEM_WR16(qlt, (&req[0xC]), 1);
3800         QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr);
3801         QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid);
3802         if (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT) {
3803                 req[0x1b] = (uint8_t)((cmd->cmd_lportid >> 16) & 0xff);
3804                 req[0x1c] = (uint8_t)(cmd->cmd_lportid & 0xff);
3805                 req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff);
3806         }
3807         QMEM_WR32(qlt, (&req[0x24]), els->els_resp_size);
3808         QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
3809         QMEM_WR32(qlt, (&req[0x30]), els->els_resp_size);
3810         qlt_submit_req_entries(qlt, 1);
3811         mutex_exit(&qlt->req_lock);
3812 
3813         return (FCT_SUCCESS);
3814 }
3815 
3816 fct_status_t
3817 qlt_send_abts_response(qlt_state_t *qlt, fct_cmd_t *cmd, int terminate)
3818 {
3819         qlt_abts_cmd_t *qcmd;
3820         fct_rcvd_abts_t *abts = (fct_rcvd_abts_t *)cmd->cmd_specific;
3821         uint8_t *req;
3822         uint32_t lportid;
3823         uint32_t fctl;
3824         int i;
3825 
3826         qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
3827 
3828         mutex_enter(&qlt->req_lock);
3829         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
3830         if (req == NULL) {
3831                 mutex_exit(&qlt->req_lock);
3832                 return (FCT_BUSY);
3833         }
3834         bcopy(qcmd->buf, req, IOCB_SIZE);
3835         lportid = QMEM_RD32(qlt, req+0x14) & 0xFFFFFF;
3836         fctl = QMEM_RD32(qlt, req+0x1C);
3837         fctl = ((fctl ^ BIT_23) & ~BIT_22) | (BIT_19 | BIT_16);
3838         req[0] = 0x55; req[1] = 1; req[2] = (uint8_t)terminate;
3839         QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
3840         if (cmd->cmd_rp)
3841                 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
3842         else
3843                 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp_handle);
3844         if (terminate) {
3845                 QMEM_WR16(qlt, (&req[0xC]), 1);
3846         }
3847         QMEM_WR32(qlt, req+0x14, cmd->cmd_rportid);
3848         req[0x17] = abts->abts_resp_rctl;
3849         QMEM_WR32(qlt, req+0x18, lportid);
3850         QMEM_WR32(qlt, req+0x1C, fctl);
3851         req[0x23]++;
3852         for (i = 0; i < 12; i += 4) {
3853                 /* Take care of firmware's LE requirement */
3854                 req[0x2C+i] = abts->abts_resp_payload[i+3];
3855                 req[0x2C+i+1] = abts->abts_resp_payload[i+2];
3856                 req[0x2C+i+2] = abts->abts_resp_payload[i+1];
3857                 req[0x2C+i+3] = abts->abts_resp_payload[i];
3858         }
3859         qlt_submit_req_entries(qlt, 1);
3860         mutex_exit(&qlt->req_lock);
3861 
3862         return (FCT_SUCCESS);
3863 }
3864 
3865 static void
3866 qlt_handle_inot(qlt_state_t *qlt, uint8_t *inot)
3867 {
3868         int i;
3869         uint32_t d;
3870         caddr_t req;
3871         /* Just put it on the request queue */
3872         mutex_enter(&qlt->req_lock);
3873         req = qlt_get_req_entries(qlt, 1);
3874         if (req == NULL) {
3875                 mutex_exit(&qlt->req_lock);
3876                 /* XXX handle this */
3877                 return;
3878         }
3879         for (i = 0; i < 16; i++) {
3880                 d = QMEM_RD32(qlt, inot);
3881                 inot += 4;
3882                 QMEM_WR32(qlt, req, d);
3883                 req += 4;
3884         }
3885         req -= 64;
3886         req[0] = 0x0e;
3887         qlt_submit_req_entries(qlt, 1);
3888         mutex_exit(&qlt->req_lock);
3889 }
3890 
3891 uint8_t qlt_task_flags[] = { 1, 3, 2, 1, 4, 0, 1, 1 };
3892 static void
3893 qlt_handle_atio(qlt_state_t *qlt, uint8_t *atio)
3894 {
3895         fct_cmd_t       *cmd;
3896         scsi_task_t     *task;
3897         qlt_cmd_t       *qcmd;
3898         uint32_t        rportid, fw_xchg_addr;
3899         uint8_t         *p, *q, *req, tm;
3900         uint16_t        cdb_size, flags, oxid;
3901         char            info[QLT_INFO_LEN];
3902 
3903         /*
3904          * If either bidirection xfer is requested of there is extended
3905          * CDB, atio[0x20 + 11] will be greater than or equal to 3.
3906          */
3907         cdb_size = 16;
3908         if (atio[0x20 + 11] >= 3) {
3909                 uint8_t b = atio[0x20 + 11];
3910                 uint16_t b1;
3911                 if ((b & 3) == 3) {
3912                         EL(qlt, "bidirectional I/O not supported\n");
3913                         cmn_err(CE_WARN, "qlt(%d) CMD with bidirectional I/O "
3914                             "received, dropping the cmd as bidirectional "
3915                             " transfers are not yet supported", qlt->instance);
3916                         /* XXX abort the I/O */
3917                         return;
3918                 }
3919                 cdb_size = (uint16_t)(cdb_size + (b & 0xfc));
3920                 /*
3921                  * Verify that we have enough entries. Without additional CDB
3922                  * Everything will fit nicely within the same 64 bytes. So the
3923                  * additional cdb size is essentially the # of additional bytes
3924                  * we need.
3925                  */
3926                 b1 = (uint16_t)b;
3927                 if (((((b1 & 0xfc) + 63) >> 6) + 1) > ((uint16_t)atio[1])) {
3928                         EL(qlt, "extended cdb received\n");
3929                         cmn_err(CE_WARN, "qlt(%d): cmd received with extended "
3930                             " cdb (cdb size = %d bytes), however the firmware "
3931                             " did not DMAed the entire FCP_CMD IU, entry count "
3932                             " is %d while it should be %d", qlt->instance,
3933                             cdb_size, atio[1], ((((b1 & 0xfc) + 63) >> 6) + 1));
3934                         /* XXX abort the I/O */
3935                         return;
3936                 }
3937         }
3938 
3939         rportid = (((uint32_t)atio[8 + 5]) << 16) |
3940             (((uint32_t)atio[8 + 6]) << 8) | atio[8+7];
3941         fw_xchg_addr = QMEM_RD32(qlt, atio+4);
3942         oxid = (uint16_t)((((uint16_t)atio[8 + 16]) << 8) | atio[8+17]);
3943 
3944         if (fw_xchg_addr == 0xFFFFFFFF) {
3945                 EL(qlt, "fw_xchg_addr==0xFFFFFFFF\n");
3946                 cmd = NULL;
3947         } else {
3948                 cmd = fct_scsi_task_alloc(qlt->qlt_port, FCT_HANDLE_NONE,
3949                     rportid, atio+0x20, cdb_size, STMF_TASK_EXT_NONE);
3950                 if (cmd == NULL) {
3951                         EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
3952                 }
3953         }
3954         if (cmd == NULL) {
3955                 EL(qlt, "fct_scsi_task_alloc cmd==NULL\n");
3956                 /* Abort this IO */
3957                 flags = (uint16_t)(BIT_14 | ((atio[3] & 0xF0) << 5));
3958 
3959                 mutex_enter(&qlt->req_lock);
3960                 req = (uint8_t *)qlt_get_req_entries(qlt, 1);
3961                 if (req == NULL) {
3962                         mutex_exit(&qlt->req_lock);
3963 
3964                         (void) snprintf(info, sizeof (info),
3965                             "qlt_handle_atio: qlt-%p, can't "
3966                             "allocate space for scsi_task", (void *)qlt);
3967                         (void) fct_port_shutdown(qlt->qlt_port,
3968                             STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
3969                         return;
3970                 }
3971                 bzero(req, IOCB_SIZE);
3972                 req[0] = 0x12; req[1] = 0x1;
3973                 QMEM_WR32(qlt, req+4, 0);
3974                 QMEM_WR16(qlt, req+8, fct_get_rp_handle(qlt->qlt_port,
3975                     rportid));
3976                 QMEM_WR16(qlt, req+10, 60);
3977                 QMEM_WR32(qlt, req+0x10, rportid);
3978                 QMEM_WR32(qlt, req+0x14, fw_xchg_addr);
3979                 QMEM_WR16(qlt, req+0x1A, flags);
3980                 QMEM_WR16(qlt, req+0x20, oxid);
3981                 qlt_submit_req_entries(qlt, 1);
3982                 mutex_exit(&qlt->req_lock);
3983 
3984                 return;
3985         }
3986 
3987         task = (scsi_task_t *)cmd->cmd_specific;
3988         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
3989         qcmd->fw_xchg_addr = fw_xchg_addr;
3990         qcmd->param.atio_byte3 = atio[3];
3991         cmd->cmd_oxid = oxid;
3992         cmd->cmd_rxid = (uint16_t)((((uint16_t)atio[8 + 18]) << 8) |
3993             atio[8+19]);
3994         cmd->cmd_rportid = rportid;
3995         cmd->cmd_lportid = (((uint32_t)atio[8 + 1]) << 16) |
3996             (((uint32_t)atio[8 + 2]) << 8) | atio[8 + 3];
3997         cmd->cmd_rp_handle = FCT_HANDLE_NONE;
3998         /* Dont do a 64 byte read as this is IOMMU */
3999         q = atio+0x28;
4000         /* XXX Handle fcp_cntl */
4001         task->task_cmd_seq_no = (uint32_t)(*q++);
4002         task->task_csn_size = 8;
4003         task->task_flags = qlt_task_flags[(*q++) & 7];
4004         tm = *q++;
4005         if (tm) {
4006                 if (tm & BIT_1)
4007                         task->task_mgmt_function = TM_ABORT_TASK_SET;
4008                 else if (tm & BIT_2)
4009                         task->task_mgmt_function = TM_CLEAR_TASK_SET;
4010                 else if (tm & BIT_4)
4011                         task->task_mgmt_function = TM_LUN_RESET;
4012                 else if (tm & BIT_5)
4013                         task->task_mgmt_function = TM_TARGET_COLD_RESET;
4014                 else if (tm & BIT_6)
4015                         task->task_mgmt_function = TM_CLEAR_ACA;
4016                 else
4017                         task->task_mgmt_function = TM_ABORT_TASK;
4018         }
4019         task->task_max_nbufs = STMF_BUFS_MAX;
4020         task->task_csn_size = 8;
4021         task->task_flags = (uint8_t)(task->task_flags | (((*q++) & 3) << 5));
4022         p = task->task_cdb;
4023         *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
4024         *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
4025         *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
4026         *p++ = *q++; *p++ = *q++; *p++ = *q++; *p++ = *q++;
4027         if (cdb_size > 16) {
4028                 uint16_t xtra = (uint16_t)(cdb_size - 16);
4029                 uint16_t i;
4030                 uint8_t cb[4];
4031 
4032                 while (xtra) {
4033                         *p++ = *q++;
4034                         xtra--;
4035                         if (q == ((uint8_t *)qlt->queue_mem_ptr +
4036                             ATIO_QUEUE_OFFSET + (ATIO_QUEUE_ENTRIES * 64))) {
4037                                 q = (uint8_t *)qlt->queue_mem_ptr +
4038                                     ATIO_QUEUE_OFFSET;
4039                         }
4040                 }
4041                 for (i = 0; i < 4; i++) {
4042                         cb[i] = *q++;
4043                         if (q == ((uint8_t *)qlt->queue_mem_ptr +
4044                             ATIO_QUEUE_OFFSET + (ATIO_QUEUE_ENTRIES * 64))) {
4045                                 q = (uint8_t *)qlt->queue_mem_ptr +
4046                                     ATIO_QUEUE_OFFSET;
4047                         }
4048                 }
4049                 task->task_expected_xfer_length = (((uint32_t)cb[0]) << 24) |
4050                     (((uint32_t)cb[1]) << 16) |
4051                     (((uint32_t)cb[2]) << 8) | cb[3];
4052         } else {
4053                 task->task_expected_xfer_length = (((uint32_t)q[0]) << 24) |
4054                     (((uint32_t)q[1]) << 16) |
4055                     (((uint32_t)q[2]) << 8) | q[3];
4056         }
4057         fct_post_rcvd_cmd(cmd, 0);
4058 }
4059 
4060 static void
4061 qlt_handle_dereg_completion(qlt_state_t *qlt, uint8_t *rsp)
4062 {
4063         uint16_t status;
4064         uint32_t portid;
4065         uint32_t subcode1, subcode2;
4066 
4067         status = QMEM_RD16(qlt, rsp+8);
4068         portid = QMEM_RD32(qlt, rsp+0x10) & 0xffffff;
4069         subcode1 = QMEM_RD32(qlt, rsp+0x14);
4070         subcode2 = QMEM_RD32(qlt, rsp+0x18);
4071 
4072         mutex_enter(&qlt->preq_lock);
4073         if (portid != qlt->rp_id_in_dereg) {
4074                 int instance = ddi_get_instance(qlt->dip);
4075 
4076                 EL(qlt, "implicit logout reveived portid = %xh\n", portid);
4077                 cmn_err(CE_WARN, "qlt(%d): implicit logout completion for 0x%x"
4078                     " received when driver wasn't waiting for it",
4079                     instance, portid);
4080                 mutex_exit(&qlt->preq_lock);
4081                 return;
4082         }
4083 
4084         if (status != 0) {
4085                 EL(qlt, "implicit logout completed for %xh with status %xh, "
4086                     "subcode1 %xh subcode2 %xh\n", portid, status, subcode1,
4087                     subcode2);
4088                 if (status == 0x31 && subcode1 == 0x0a) {
4089                         qlt->rp_dereg_status = FCT_SUCCESS;
4090                 } else {
4091                         EL(qlt, "implicit logout portid=%xh, status=%xh, "
4092                             "subcode1=%xh, subcode2=%xh\n", portid, status,
4093                             subcode1, subcode2);
4094                         qlt->rp_dereg_status =
4095                             QLT_FIRMWARE_ERROR(status, subcode1, subcode2);
4096                 }
4097         } else {
4098                 qlt->rp_dereg_status = FCT_SUCCESS;
4099         }
4100         cv_signal(&qlt->rp_dereg_cv);
4101         mutex_exit(&qlt->preq_lock);
4102 }
4103 
4104 /*
4105  * Note that when an ELS is aborted, the regular or aborted completion
4106  * (if any) gets posted before the abort IOCB comes back on response queue.
4107  */
4108 static void
4109 qlt_handle_unsol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
4110 {
4111         char            info[QLT_INFO_LEN];
4112         fct_cmd_t       *cmd;
4113         qlt_cmd_t       *qcmd;
4114         uint32_t        hndl;
4115         uint32_t        subcode1, subcode2;
4116         uint16_t        status;
4117 
4118         hndl = QMEM_RD32(qlt, rsp+4);
4119         status = QMEM_RD16(qlt, rsp+8);
4120         subcode1 = QMEM_RD32(qlt, rsp+0x24);
4121         subcode2 = QMEM_RD32(qlt, rsp+0x28);
4122 
4123         if (!CMD_HANDLE_VALID(hndl)) {
4124                 EL(qlt, "handle = %xh\n", hndl);
4125                 /*
4126                  * This cannot happen for unsol els completion. This can
4127                  * only happen when abort for an unsol els completes.
4128                  * This condition indicates a firmware bug.
4129                  */
4130                 (void) snprintf(info, sizeof (info),
4131                     "qlt_handle_unsol_els_completion: "
4132                     "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
4133                     hndl, status, subcode1, subcode2, (void *)rsp);
4134                 (void) fct_port_shutdown(qlt->qlt_port,
4135                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4136                     STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4137                 return;
4138         }
4139 
4140         if (status == 5) {
4141                 /*
4142                  * When an unsolicited els is aborted, the abort is done
4143                  * by a ELSPT iocb with abort control. This is the aborted IOCB
4144                  * and not the abortee. We will do the cleanup when the
4145                  * IOCB which caused the abort, returns.
4146                  */
4147                 EL(qlt, "status = %xh\n", status);
4148                 stmf_trace(0, "--UNSOL ELS returned with status 5 --");
4149                 return;
4150         }
4151 
4152         cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
4153         if (cmd == NULL) {
4154                 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
4155                 /*
4156                  * Now why would this happen ???
4157                  */
4158                 (void) snprintf(info, sizeof (info),
4159                     "qlt_handle_unsol_els_completion: can not "
4160                     "get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
4161                     (void *)rsp);
4162                 (void) fct_port_shutdown(qlt->qlt_port,
4163                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4164 
4165                 return;
4166         }
4167 
4168         ASSERT(cmd->cmd_type == FCT_CMD_RCVD_ELS);
4169         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4170         if (qcmd->flags & QLT_CMD_ABORTING) {
4171                 /*
4172                  * This is the same case as "if (status == 5)" above. The
4173                  * only difference is that in this case the firmware actually
4174                  * finished sending the response. So the abort attempt will
4175                  * come back with status ?. We will handle it there.
4176                  */
4177                 stmf_trace(0, "--UNSOL ELS finished while we are trying to "
4178                     "abort it");
4179                 return;
4180         }
4181 
4182         if (qcmd->dbuf != NULL) {
4183                 qlt_dmem_free(NULL, qcmd->dbuf);
4184                 qcmd->dbuf = NULL;
4185         }
4186 
4187         if (status == 0) {
4188                 fct_send_response_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
4189         } else {
4190                 fct_send_response_done(cmd,
4191                     QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
4192         }
4193 }
4194 
4195 static void
4196 qlt_handle_unsol_els_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
4197 {
4198         char            info[QLT_INFO_LEN];
4199         fct_cmd_t       *cmd;
4200         qlt_cmd_t       *qcmd;
4201         uint32_t        hndl;
4202         uint32_t        subcode1, subcode2;
4203         uint16_t        status;
4204 
4205         hndl = QMEM_RD32(qlt, rsp+4);
4206         status = QMEM_RD16(qlt, rsp+8);
4207         subcode1 = QMEM_RD32(qlt, rsp+0x24);
4208         subcode2 = QMEM_RD32(qlt, rsp+0x28);
4209 
4210         if (!CMD_HANDLE_VALID(hndl)) {
4211                 EL(qlt, "handle = %xh\n", hndl);
4212                 ASSERT(hndl == 0);
4213                 /*
4214                  * Someone has requested to abort it, but no one is waiting for
4215                  * this completion.
4216                  */
4217                 if ((status != 0) && (status != 8)) {
4218                         EL(qlt, "status = %xh\n", status);
4219                         /*
4220                          * There could be exchange resource leakage, so
4221                          * throw HBA fatal error event now
4222                          */
4223                         (void) snprintf(info, sizeof (info),
4224                             "qlt_handle_unsol_els_abort_completion: "
4225                             "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
4226                             hndl, status, subcode1, subcode2, (void *)rsp);
4227                         (void) fct_port_shutdown(qlt->qlt_port,
4228                             STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4229                             STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4230                         return;
4231                 }
4232 
4233                 return;
4234         }
4235 
4236         cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
4237         if (cmd == NULL) {
4238                 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
4239                 /*
4240                  * Why would this happen ??
4241                  */
4242                 (void) snprintf(info, sizeof (info),
4243                     "qlt_handle_unsol_els_abort_completion: can not get "
4244                     "cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
4245                     (void *)rsp);
4246                 (void) fct_port_shutdown(qlt->qlt_port,
4247                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4248 
4249                 return;
4250         }
4251 
4252         ASSERT(cmd->cmd_type == FCT_CMD_RCVD_ELS);
4253         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4254         ASSERT(qcmd->flags & QLT_CMD_ABORTING);
4255 
4256         if (qcmd->dbuf != NULL) {
4257                 qlt_dmem_free(NULL, qcmd->dbuf);
4258                 qcmd->dbuf = NULL;
4259         }
4260 
4261         if (status == 0) {
4262                 fct_cmd_fca_aborted(cmd, FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
4263         } else if (status == 8) {
4264                 fct_cmd_fca_aborted(cmd, FCT_NOT_FOUND, FCT_IOF_FCA_DONE);
4265         } else {
4266                 fct_cmd_fca_aborted(cmd,
4267                     QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
4268         }
4269 }
4270 
4271 static void
4272 qlt_handle_sol_els_completion(qlt_state_t *qlt, uint8_t *rsp)
4273 {
4274         char            info[QLT_INFO_LEN];
4275         fct_cmd_t       *cmd;
4276         fct_els_t       *els;
4277         qlt_cmd_t       *qcmd;
4278         uint32_t        hndl;
4279         uint32_t        subcode1, subcode2;
4280         uint16_t        status;
4281 
4282         hndl = QMEM_RD32(qlt, rsp+4);
4283         status = QMEM_RD16(qlt, rsp+8);
4284         subcode1 = QMEM_RD32(qlt, rsp+0x24);
4285         subcode2 = QMEM_RD32(qlt, rsp+0x28);
4286 
4287         if (!CMD_HANDLE_VALID(hndl)) {
4288                 EL(qlt, "handle = %xh\n", hndl);
4289                 /*
4290                  * This cannot happen for sol els completion.
4291                  */
4292                 (void) snprintf(info, sizeof (info),
4293                     "qlt_handle_sol_els_completion: "
4294                     "Invalid handle: hndl-%x, status-%x/%x/%x, rsp-%p",
4295                     hndl, status, subcode1, subcode2, (void *)rsp);
4296                 (void) fct_port_shutdown(qlt->qlt_port,
4297                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4298                     STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4299                 return;
4300         }
4301 
4302         cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
4303         if (cmd == NULL) {
4304                 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
4305                 (void) snprintf(info, sizeof (info),
4306                     "qlt_handle_sol_els_completion: can not "
4307                     "get cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
4308                     (void *)rsp);
4309                 (void) fct_port_shutdown(qlt->qlt_port,
4310                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4311 
4312                 return;
4313         }
4314 
4315         ASSERT(cmd->cmd_type == FCT_CMD_SOL_ELS);
4316         els = (fct_els_t *)cmd->cmd_specific;
4317         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4318         qcmd->fw_xchg_addr = QMEM_RD32(qlt, (&rsp[0x10]));
4319 
4320         if (qcmd->flags & QLT_CMD_ABORTING) {
4321                 /*
4322                  * We will handle it when the ABORT IO IOCB returns.
4323                  */
4324                 return;
4325         }
4326 
4327         if (qcmd->dbuf != NULL) {
4328                 if (status == 0) {
4329                         qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL);
4330                         bcopy(qcmd->dbuf->db_sglist[0].seg_addr +
4331                             qcmd->param.resp_offset,
4332                             els->els_resp_payload, els->els_resp_size);
4333                 }
4334                 qlt_dmem_free(NULL, qcmd->dbuf);
4335                 qcmd->dbuf = NULL;
4336         }
4337 
4338         if (status == 0) {
4339                 fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
4340         } else {
4341                 fct_send_cmd_done(cmd,
4342                     QLT_FIRMWARE_ERROR(status, subcode1, subcode2), 0);
4343         }
4344 }
4345 
4346 static void
4347 qlt_handle_ct_completion(qlt_state_t *qlt, uint8_t *rsp)
4348 {
4349         fct_cmd_t       *cmd;
4350         fct_sol_ct_t    *ct;
4351         qlt_cmd_t       *qcmd;
4352         uint32_t         hndl;
4353         uint16_t         status;
4354         char             info[QLT_INFO_LEN];
4355 
4356         hndl = QMEM_RD32(qlt, rsp+4);
4357         status = QMEM_RD16(qlt, rsp+8);
4358 
4359         if (!CMD_HANDLE_VALID(hndl)) {
4360                 EL(qlt, "handle = %xh\n", hndl);
4361                 /*
4362                  * Solicited commands will always have a valid handle.
4363                  */
4364                 (void) snprintf(info, sizeof (info),
4365                     "qlt_handle_ct_completion: "
4366                     "hndl-%x, status-%x, rsp-%p", hndl, status, (void *)rsp);
4367                 (void) fct_port_shutdown(qlt->qlt_port,
4368                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4369                     STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4370                 return;
4371         }
4372 
4373         cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
4374         if (cmd == NULL) {
4375                 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
4376                 (void) snprintf(info, sizeof (info),
4377                     "qlt_handle_ct_completion: cannot find "
4378                     "cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
4379                     (void *)rsp);
4380                 (void) fct_port_shutdown(qlt->qlt_port,
4381                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4382 
4383                 return;
4384         }
4385 
4386         ct = (fct_sol_ct_t *)cmd->cmd_specific;
4387         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4388         ASSERT(cmd->cmd_type == FCT_CMD_SOL_CT);
4389 
4390         if (qcmd->flags & QLT_CMD_ABORTING) {
4391                 /*
4392                  * We will handle it when ABORT IO IOCB returns;
4393                  */
4394                 return;
4395         }
4396 
4397         ASSERT(qcmd->dbuf);
4398         if (status == 0) {
4399                 qlt_dmem_dma_sync(qcmd->dbuf, DDI_DMA_SYNC_FORKERNEL);
4400                 bcopy(qcmd->dbuf->db_sglist[0].seg_addr +
4401                     qcmd->param.resp_offset,
4402                     ct->ct_resp_payload, ct->ct_resp_size);
4403         }
4404         qlt_dmem_free(NULL, qcmd->dbuf);
4405         qcmd->dbuf = NULL;
4406 
4407         if (status == 0) {
4408                 fct_send_cmd_done(cmd, FCT_SUCCESS, FCT_IOF_FCA_DONE);
4409         } else {
4410                 fct_send_cmd_done(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
4411         }
4412 }
4413 
4414 static void
4415 qlt_handle_ctio_completion(qlt_state_t *qlt, uint8_t *rsp)
4416 {
4417         fct_cmd_t       *cmd;
4418         scsi_task_t     *task;
4419         qlt_cmd_t       *qcmd;
4420         stmf_data_buf_t *dbuf;
4421         fct_status_t    fc_st;
4422         uint32_t        iof = 0;
4423         uint32_t        hndl;
4424         uint16_t        status;
4425         uint16_t        flags;
4426         uint8_t         abort_req;
4427         uint8_t         n;
4428         char            info[QLT_INFO_LEN];
4429 
4430         /* XXX: Check validity of the IOCB by checking 4th byte. */
4431         hndl = QMEM_RD32(qlt, rsp+4);
4432         status = QMEM_RD16(qlt, rsp+8);
4433         flags = QMEM_RD16(qlt, rsp+0x1a);
4434         n = rsp[2];
4435 
4436         if (!CMD_HANDLE_VALID(hndl)) {
4437                 EL(qlt, "handle = %xh\n", hndl);
4438                 ASSERT(hndl == 0);
4439                 /*
4440                  * Someone has requested to abort it, but no one is waiting for
4441                  * this completion.
4442                  */
4443                 EL(qlt, "hndl-%xh, status-%xh, rsp-%p\n", hndl, status,
4444                     (void *)rsp);
4445                 if ((status != 1) && (status != 2)) {
4446                         EL(qlt, "status = %xh\n", status);
4447                         /*
4448                          * There could be exchange resource leakage, so
4449                          * throw HBA fatal error event now
4450                          */
4451                         (void) snprintf(info, sizeof (info),
4452                             "qlt_handle_ctio_completion: hndl-"
4453                             "%x, status-%x, rsp-%p", hndl, status, (void *)rsp);
4454                         (void) fct_port_shutdown(qlt->qlt_port,
4455                             STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4456 
4457                 }
4458 
4459                 return;
4460         }
4461 
4462         if (flags & BIT_14) {
4463                 abort_req = 1;
4464                 EL(qlt, "abort: hndl-%x, status-%x, rsp-%p\n", hndl, status,
4465                     (void *)rsp);
4466         } else {
4467                 abort_req = 0;
4468         }
4469 
4470         cmd = fct_handle_to_cmd(qlt->qlt_port, hndl);
4471         if (cmd == NULL) {
4472                 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", hndl);
4473                 (void) snprintf(info, sizeof (info),
4474                     "qlt_handle_ctio_completion: cannot find "
4475                     "cmd, hndl-%x, status-%x, rsp-%p", hndl, status,
4476                     (void *)rsp);
4477                 (void) fct_port_shutdown(qlt->qlt_port,
4478                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4479 
4480                 return;
4481         }
4482 
4483         task = (scsi_task_t *)cmd->cmd_specific;
4484         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4485         if (qcmd->dbuf_rsp_iu) {
4486                 ASSERT((flags & (BIT_6 | BIT_7)) == BIT_7);
4487                 qlt_dmem_free(NULL, qcmd->dbuf_rsp_iu);
4488                 qcmd->dbuf_rsp_iu = NULL;
4489         }
4490 
4491         if ((status == 1) || (status == 2)) {
4492                 if (abort_req) {
4493                         fc_st = FCT_ABORT_SUCCESS;
4494                         iof = FCT_IOF_FCA_DONE;
4495                 } else {
4496                         fc_st = FCT_SUCCESS;
4497                         if (flags & BIT_15) {
4498                                 iof = FCT_IOF_FCA_DONE;
4499                         }
4500                 }
4501         } else {
4502                 EL(qlt, "status = %xh\n", status);
4503                 if ((status == 8) && abort_req) {
4504                         fc_st = FCT_NOT_FOUND;
4505                         iof = FCT_IOF_FCA_DONE;
4506                 } else {
4507                         fc_st = QLT_FIRMWARE_ERROR(status, 0, 0);
4508                 }
4509         }
4510         dbuf = NULL;
4511         if (((n & BIT_7) == 0) && (!abort_req)) {
4512                 /* A completion of data xfer */
4513                 if (n == 0) {
4514                         dbuf = qcmd->dbuf;
4515                 } else {
4516                         dbuf = stmf_handle_to_buf(task, n);
4517                 }
4518 
4519                 ASSERT(dbuf != NULL);
4520                 if (dbuf->db_flags & DB_DIRECTION_FROM_RPORT)
4521                         qlt_dmem_dma_sync(dbuf, DDI_DMA_SYNC_FORCPU);
4522                 if (flags & BIT_15) {
4523                         dbuf->db_flags = (uint16_t)(dbuf->db_flags |
4524                             DB_STATUS_GOOD_SENT);
4525                 }
4526 
4527                 dbuf->db_xfer_status = fc_st;
4528                 fct_scsi_data_xfer_done(cmd, dbuf, iof);
4529                 return;
4530         }
4531         if (!abort_req) {
4532                 /*
4533                  * This was just a pure status xfer.
4534                  */
4535                 fct_send_response_done(cmd, fc_st, iof);
4536                 return;
4537         }
4538 
4539         fct_cmd_fca_aborted(cmd, fc_st, iof);
4540 }
4541 
4542 static void
4543 qlt_handle_sol_abort_completion(qlt_state_t *qlt, uint8_t *rsp)
4544 {
4545         char            info[QLT_INFO_LEN];
4546         fct_cmd_t       *cmd;
4547         qlt_cmd_t       *qcmd;
4548         uint32_t        h;
4549         uint16_t        status;
4550 
4551         h = QMEM_RD32(qlt, rsp+4);
4552         status = QMEM_RD16(qlt, rsp+8);
4553 
4554         if (!CMD_HANDLE_VALID(h)) {
4555                 EL(qlt, "handle = %xh\n", h);
4556                 /*
4557                  * Solicited commands always have a valid handle.
4558                  */
4559                 (void) snprintf(info, sizeof (info),
4560                     "qlt_handle_sol_abort_completion: hndl-"
4561                     "%x, status-%x, rsp-%p", h, status, (void *)rsp);
4562                 (void) fct_port_shutdown(qlt->qlt_port,
4563                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET |
4564                     STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4565                 return;
4566         }
4567         cmd = fct_handle_to_cmd(qlt->qlt_port, h);
4568         if (cmd == NULL) {
4569                 EL(qlt, "fct_handle_to_cmd cmd==NULL, hndl=%xh\n", h);
4570                 /*
4571                  * What happened to the cmd ??
4572                  */
4573                 (void) snprintf(info, sizeof (info),
4574                     "qlt_handle_sol_abort_completion: cannot "
4575                     "find cmd, hndl-%x, status-%x, rsp-%p", h, status,
4576                     (void *)rsp);
4577                 (void) fct_port_shutdown(qlt->qlt_port,
4578                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4579 
4580                 return;
4581         }
4582 
4583         ASSERT((cmd->cmd_type == FCT_CMD_SOL_ELS) ||
4584             (cmd->cmd_type == FCT_CMD_SOL_CT));
4585         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4586         if (qcmd->dbuf != NULL) {
4587                 qlt_dmem_free(NULL, qcmd->dbuf);
4588                 qcmd->dbuf = NULL;
4589         }
4590         ASSERT(qcmd->flags & QLT_CMD_ABORTING);
4591         if (status == 0) {
4592                 fct_cmd_fca_aborted(cmd, FCT_ABORT_SUCCESS, FCT_IOF_FCA_DONE);
4593         } else if (status == 0x31) {
4594                 fct_cmd_fca_aborted(cmd, FCT_NOT_FOUND, FCT_IOF_FCA_DONE);
4595         } else {
4596                 fct_cmd_fca_aborted(cmd, QLT_FIRMWARE_ERROR(status, 0, 0), 0);
4597         }
4598 }
4599 
4600 static void
4601 qlt_handle_rcvd_abts(qlt_state_t *qlt, uint8_t *resp)
4602 {
4603         qlt_abts_cmd_t  *qcmd;
4604         fct_cmd_t       *cmd;
4605         uint32_t        remote_portid;
4606         char            info[QLT_INFO_LEN];
4607 
4608         remote_portid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x18])))) |
4609             ((uint32_t)(resp[0x1A])) << 16;
4610         cmd = (fct_cmd_t *)fct_alloc(FCT_STRUCT_CMD_RCVD_ABTS,
4611             sizeof (qlt_abts_cmd_t), 0);
4612         if (cmd == NULL) {
4613                 EL(qlt, "fct_alloc cmd==NULL\n");
4614                 (void) snprintf(info, sizeof (info),
4615                     "qlt_handle_rcvd_abts: qlt-%p, can't "
4616                     "allocate space for fct_cmd", (void *)qlt);
4617                 (void) fct_port_shutdown(qlt->qlt_port,
4618                     STMF_RFLAG_FATAL_ERROR | STMF_RFLAG_RESET, info);
4619                 return;
4620         }
4621 
4622         resp[0xC] = resp[0xD] = resp[0xE] = 0;
4623         qcmd = (qlt_abts_cmd_t *)cmd->cmd_fca_private;
4624         bcopy(resp, qcmd->buf, IOCB_SIZE);
4625         cmd->cmd_port = qlt->qlt_port;
4626         cmd->cmd_rp_handle = QMEM_RD16(qlt, resp+0xA);
4627         if (cmd->cmd_rp_handle == 0xFFFF)
4628                 cmd->cmd_rp_handle = FCT_HANDLE_NONE;
4629 
4630         cmd->cmd_rportid = remote_portid;
4631         cmd->cmd_lportid = ((uint32_t)(QMEM_RD16(qlt, (&resp[0x14])))) |
4632             ((uint32_t)(resp[0x16])) << 16;
4633         cmd->cmd_oxid = QMEM_RD16(qlt, (&resp[0x26]));
4634         cmd->cmd_rxid = QMEM_RD16(qlt, (&resp[0x24]));
4635         fct_post_rcvd_cmd(cmd, 0);
4636 }
4637 
4638 static void
4639 qlt_handle_abts_completion(qlt_state_t *qlt, uint8_t *resp)
4640 {
4641         uint16_t status;
4642         char    info[QLT_INFO_LEN];
4643 
4644         status = QMEM_RD16(qlt, resp+8);
4645 
4646         if ((status == 0) || (status == 5)) {
4647                 return;
4648         }
4649         EL(qlt, "status = %xh\n", status);
4650         (void) snprintf(info, sizeof (info),
4651             "ABTS completion failed %x/%x/%x resp_off %x",
4652             status, QMEM_RD32(qlt, resp+0x34), QMEM_RD32(qlt, resp+0x38),
4653             ((uint32_t)(qlt->resp_ndx_to_fw)) << 6);
4654         (void) fct_port_shutdown(qlt->qlt_port, STMF_RFLAG_FATAL_ERROR |
4655             STMF_RFLAG_RESET | STMF_RFLAG_COLLECT_DEBUG_DUMP, info);
4656 }
4657 
4658 #ifdef  DEBUG
4659 uint32_t qlt_drop_abort_counter = 0;
4660 #endif
4661 
4662 fct_status_t
4663 qlt_abort_cmd(struct fct_local_port *port, fct_cmd_t *cmd, uint32_t flags)
4664 {
4665         qlt_state_t *qlt = (qlt_state_t *)port->port_fca_private;
4666 
4667         if ((qlt->qlt_state == FCT_STATE_OFFLINE) ||
4668             (qlt->qlt_state == FCT_STATE_OFFLINING)) {
4669                 return (FCT_NOT_FOUND);
4670         }
4671 
4672 #ifdef DEBUG
4673         if (qlt_drop_abort_counter > 0) {
4674                 if (atomic_dec_32_nv(&qlt_drop_abort_counter) == 1)
4675                         return (FCT_SUCCESS);
4676         }
4677 #endif
4678 
4679         if (cmd->cmd_type == FCT_CMD_FCP_XCHG) {
4680                 return (qlt_abort_unsol_scsi_cmd(qlt, cmd));
4681         }
4682 
4683         if (flags & FCT_IOF_FORCE_FCA_DONE) {
4684                 cmd->cmd_handle = 0;
4685         }
4686 
4687         if (cmd->cmd_type == FCT_CMD_RCVD_ABTS) {
4688                 return (qlt_send_abts_response(qlt, cmd, 1));
4689         }
4690 
4691         if (cmd->cmd_type == FCT_CMD_RCVD_ELS) {
4692                 return (qlt_abort_purex(qlt, cmd));
4693         }
4694 
4695         if ((cmd->cmd_type == FCT_CMD_SOL_ELS) ||
4696             (cmd->cmd_type == FCT_CMD_SOL_CT)) {
4697                 return (qlt_abort_sol_cmd(qlt, cmd));
4698         }
4699         EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type);
4700 
4701         ASSERT(0);
4702         return (FCT_FAILURE);
4703 }
4704 
4705 fct_status_t
4706 qlt_abort_sol_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
4707 {
4708         uint8_t *req;
4709         qlt_cmd_t *qcmd;
4710 
4711         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4712         qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
4713         EL(qlt, "fctcmd-%p, cmd_handle-%xh\n", cmd, cmd->cmd_handle);
4714 
4715         mutex_enter(&qlt->req_lock);
4716         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
4717         if (req == NULL) {
4718                 mutex_exit(&qlt->req_lock);
4719 
4720                 return (FCT_BUSY);
4721         }
4722         bzero(req, IOCB_SIZE);
4723         req[0] = 0x33; req[1] = 1;
4724         QMEM_WR32(qlt, req+4, cmd->cmd_handle);
4725         if (cmd->cmd_rp) {
4726                 QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle);
4727         } else {
4728                 QMEM_WR16(qlt, req+8, 0xFFFF);
4729         }
4730 
4731         QMEM_WR32(qlt, req+0xc, cmd->cmd_handle);
4732         QMEM_WR32(qlt, req+0x30, cmd->cmd_rportid);
4733         qlt_submit_req_entries(qlt, 1);
4734         mutex_exit(&qlt->req_lock);
4735 
4736         return (FCT_SUCCESS);
4737 }
4738 
4739 fct_status_t
4740 qlt_abort_purex(qlt_state_t *qlt, fct_cmd_t *cmd)
4741 {
4742         uint8_t *req;
4743         qlt_cmd_t *qcmd;
4744         fct_els_t *els;
4745         uint8_t elsop, req1f;
4746 
4747         els = (fct_els_t *)cmd->cmd_specific;
4748         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4749         elsop = els->els_req_payload[0];
4750         EL(qlt, "fctcmd-%p, cmd_handle-%xh, elsop-%xh\n", cmd, cmd->cmd_handle,
4751             elsop);
4752         req1f = 0x60;   /* Terminate xchg */
4753         if ((elsop == ELS_OP_PRLI) || (elsop == ELS_OP_PRLO) ||
4754             (elsop == ELS_OP_TPRLO) || (elsop == ELS_OP_LOGO)) {
4755                 req1f = (uint8_t)(req1f | BIT_4);
4756         }
4757 
4758         mutex_enter(&qlt->req_lock);
4759         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
4760         if (req == NULL) {
4761                 mutex_exit(&qlt->req_lock);
4762 
4763                 return (FCT_BUSY);
4764         }
4765 
4766         qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
4767         bzero(req, IOCB_SIZE);
4768         req[0] = 0x53; req[1] = 1; req[0xf] = 0x10;
4769         req[0x16] = elsop; req[0x1f] = req1f;
4770         QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
4771         if (cmd->cmd_rp) {
4772                 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
4773                 EL(qlt, "rp_handle-%x\n", cmd->cmd_rp->rp_handle);
4774         } else {
4775                 QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp_handle);
4776                 EL(qlt, "cmd_rp_handle-%x\n", cmd->cmd_rp_handle);
4777         }
4778 
4779         QMEM_WR32(qlt, (&req[0x10]), qcmd->fw_xchg_addr);
4780         QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rportid);
4781         qlt_submit_req_entries(qlt, 1);
4782         mutex_exit(&qlt->req_lock);
4783 
4784         return (FCT_SUCCESS);
4785 }
4786 
4787 fct_status_t
4788 qlt_abort_unsol_scsi_cmd(qlt_state_t *qlt, fct_cmd_t *cmd)
4789 {
4790         qlt_cmd_t *qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4791         uint8_t *req;
4792         uint16_t flags;
4793 
4794         flags = (uint16_t)(BIT_14 |
4795             (((uint16_t)qcmd->param.atio_byte3 & 0xf0) << 5));
4796         EL(qlt, "fctcmd-%p, cmd_handle-%x\n", cmd, cmd->cmd_handle);
4797 
4798         mutex_enter(&qlt->req_lock);
4799         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
4800         if (req == NULL) {
4801                 mutex_exit(&qlt->req_lock);
4802 
4803                 return (FCT_BUSY);
4804         }
4805 
4806         qcmd->flags = (uint16_t)(qcmd->flags | QLT_CMD_ABORTING);
4807         bzero(req, IOCB_SIZE);
4808         req[0] = 0x12; req[1] = 0x1;
4809         QMEM_WR32(qlt, req+4, cmd->cmd_handle);
4810         QMEM_WR16(qlt, req+8, cmd->cmd_rp->rp_handle);
4811         QMEM_WR16(qlt, req+10, 60);     /* 60 seconds timeout */
4812         QMEM_WR32(qlt, req+0x10, cmd->cmd_rportid);
4813         QMEM_WR32(qlt, req+0x14, qcmd->fw_xchg_addr);
4814         QMEM_WR16(qlt, req+0x1A, flags);
4815         QMEM_WR16(qlt, req+0x20, cmd->cmd_oxid);
4816         qlt_submit_req_entries(qlt, 1);
4817         mutex_exit(&qlt->req_lock);
4818 
4819         return (FCT_SUCCESS);
4820 }
4821 
4822 fct_status_t
4823 qlt_send_cmd(fct_cmd_t *cmd)
4824 {
4825         qlt_state_t *qlt;
4826 
4827         qlt = (qlt_state_t *)cmd->cmd_port->port_fca_private;
4828         if (cmd->cmd_type == FCT_CMD_SOL_ELS) {
4829                 return (qlt_send_els(qlt, cmd));
4830         } else if (cmd->cmd_type == FCT_CMD_SOL_CT) {
4831                 return (qlt_send_ct(qlt, cmd));
4832         }
4833         EL(qlt, "cmd->cmd_type = %xh\n", cmd->cmd_type);
4834 
4835         ASSERT(0);
4836         return (FCT_FAILURE);
4837 }
4838 
4839 fct_status_t
4840 qlt_send_els(qlt_state_t *qlt, fct_cmd_t *cmd)
4841 {
4842         uint8_t *req;
4843         fct_els_t *els;
4844         qlt_cmd_t *qcmd;
4845         stmf_data_buf_t *buf;
4846         qlt_dmem_bctl_t *bctl;
4847         uint32_t sz, minsz;
4848 
4849         els = (fct_els_t *)cmd->cmd_specific;
4850         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4851         qcmd->flags = QLT_CMD_TYPE_SOLICITED;
4852         qcmd->param.resp_offset = (uint16_t)((els->els_req_size + 7) & ~7);
4853         sz = minsz = qcmd->param.resp_offset + els->els_resp_size;
4854         buf = qlt_i_dmem_alloc(qlt, sz, &minsz, 0);
4855         if (buf == NULL) {
4856                 return (FCT_BUSY);
4857         }
4858         bctl = (qlt_dmem_bctl_t *)buf->db_port_private;
4859 
4860         qcmd->dbuf = buf;
4861         bcopy(els->els_req_payload, buf->db_sglist[0].seg_addr,
4862             els->els_req_size);
4863         qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
4864 
4865         mutex_enter(&qlt->req_lock);
4866         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
4867         if (req == NULL) {
4868                 qlt_dmem_free(NULL, buf);
4869                 mutex_exit(&qlt->req_lock);
4870                 return (FCT_BUSY);
4871         }
4872         bzero(req, IOCB_SIZE);
4873         req[0] = 0x53; req[1] = 1;
4874         QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
4875         QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
4876         QMEM_WR16(qlt, (&req[0xC]), 1);
4877         QMEM_WR16(qlt, (&req[0xE]), 0x1000);
4878         QMEM_WR16(qlt, (&req[0x14]), 1);
4879         req[0x16] = els->els_req_payload[0];
4880         if (qlt->cur_topology == PORT_TOPOLOGY_PT_TO_PT) {
4881                 req[0x1b] = (uint8_t)((cmd->cmd_lportid >> 16) & 0xff);
4882                 req[0x1c] = (uint8_t)(cmd->cmd_lportid & 0xff);
4883                 req[0x1d] = (uint8_t)((cmd->cmd_lportid >> 8) & 0xff);
4884         }
4885         QMEM_WR32(qlt, (&req[0x18]), cmd->cmd_rp->rp_id);
4886         QMEM_WR32(qlt, (&req[0x20]), els->els_resp_size);
4887         QMEM_WR32(qlt, (&req[0x24]), els->els_req_size);
4888         QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr);
4889         QMEM_WR32(qlt, (&req[0x30]), els->els_req_size);
4890         QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
4891             qcmd->param.resp_offset));
4892         QMEM_WR32(qlt, (&req[0x3C]), els->els_resp_size);
4893         qlt_submit_req_entries(qlt, 1);
4894         mutex_exit(&qlt->req_lock);
4895 
4896         return (FCT_SUCCESS);
4897 }
4898 
4899 fct_status_t
4900 qlt_send_ct(qlt_state_t *qlt, fct_cmd_t *cmd)
4901 {
4902         uint8_t *req;
4903         fct_sol_ct_t *ct;
4904         qlt_cmd_t *qcmd;
4905         stmf_data_buf_t *buf;
4906         qlt_dmem_bctl_t *bctl;
4907         uint32_t sz, minsz;
4908 
4909         ct = (fct_sol_ct_t *)cmd->cmd_specific;
4910         qcmd = (qlt_cmd_t *)cmd->cmd_fca_private;
4911         qcmd->flags = QLT_CMD_TYPE_SOLICITED;
4912         qcmd->param.resp_offset = (uint16_t)((ct->ct_req_size + 7) & ~7);
4913         sz = minsz = qcmd->param.resp_offset + ct->ct_resp_size;
4914         buf = qlt_i_dmem_alloc(qlt, sz, &minsz, 0);
4915         if (buf == NULL) {
4916                 return (FCT_BUSY);
4917         }
4918         bctl = (qlt_dmem_bctl_t *)buf->db_port_private;
4919 
4920         qcmd->dbuf = buf;
4921         bcopy(ct->ct_req_payload, buf->db_sglist[0].seg_addr,
4922             ct->ct_req_size);
4923         qlt_dmem_dma_sync(buf, DDI_DMA_SYNC_FORDEV);
4924 
4925         mutex_enter(&qlt->req_lock);
4926         req = (uint8_t *)qlt_get_req_entries(qlt, 1);
4927         if (req == NULL) {
4928                 qlt_dmem_free(NULL, buf);
4929                 mutex_exit(&qlt->req_lock);
4930                 return (FCT_BUSY);
4931         }
4932         bzero(req, IOCB_SIZE);
4933         req[0] = 0x29; req[1] = 1;
4934         QMEM_WR32(qlt, (&req[4]), cmd->cmd_handle);
4935         QMEM_WR16(qlt, (&req[0xA]), cmd->cmd_rp->rp_handle);
4936         QMEM_WR16(qlt, (&req[0xC]), 1);
4937         QMEM_WR16(qlt, (&req[0x10]), 0x20); /* > (2 * RA_TOV) */
4938         QMEM_WR16(qlt, (&req[0x14]), 1);
4939 
4940         QMEM_WR32(qlt, (&req[0x20]), ct->ct_resp_size);
4941         QMEM_WR32(qlt, (&req[0x24]), ct->ct_req_size);
4942 
4943         QMEM_WR64(qlt, (&req[0x28]), bctl->bctl_dev_addr); /* COMMAND DSD */
4944         QMEM_WR32(qlt, (&req[0x30]), ct->ct_req_size);
4945         QMEM_WR64(qlt, (&req[0x34]), (bctl->bctl_dev_addr +
4946             qcmd->param.resp_offset));               /* RESPONSE DSD */
4947         QMEM_WR32(qlt, (&req[0x3C]), ct->ct_resp_size);
4948 
4949         qlt_submit_req_entries(qlt, 1);
4950         mutex_exit(&qlt->req_lock);
4951 
4952         return (FCT_SUCCESS);
4953 }
4954 
4955 
4956 /*
4957  * All QLT_FIRMWARE_* will mainly be handled in this function
4958  * It can not be called in interrupt context
4959  *
4960  * FWDUMP's purpose is to serve ioctl, so we will use qlt_ioctl_flags
4961  * and qlt_ioctl_lock
4962  */
4963 static fct_status_t
4964 qlt_firmware_dump(fct_local_port_t *port, stmf_state_change_info_t *ssci)
4965 {
4966         qlt_state_t     *qlt = (qlt_state_t *)port->port_fca_private;
4967         int             i;
4968         int             retries, n;
4969         uint_t          size_left;
4970         char            c = ' ';
4971         uint32_t        addr, endaddr, words_to_read;
4972         caddr_t         buf;
4973         fct_status_t    ret;
4974 
4975         mutex_enter(&qlt->qlt_ioctl_lock);
4976         /*
4977          * To make sure that there's no outstanding dumping task
4978          */
4979         if (qlt->qlt_ioctl_flags & QLT_FWDUMP_INPROGRESS) {
4980                 mutex_exit(&qlt->qlt_ioctl_lock);
4981                 EL(qlt, "qlt_ioctl_flags=%xh, inprogress\n",
4982                     qlt->qlt_ioctl_flags);
4983                 EL(qlt, "outstanding\n");
4984                 return (FCT_FAILURE);
4985         }
4986 
4987         /*
4988          * To make sure not to overwrite existing dump
4989          */
4990         if ((qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID) &&
4991             !(qlt->qlt_ioctl_flags & QLT_FWDUMP_TRIGGERED_BY_USER) &&
4992             !(qlt->qlt_ioctl_flags & QLT_FWDUMP_FETCHED_BY_USER)) {
4993                 /*
4994                  * If we have alreay one dump, but it's not triggered by user
4995                  * and the user hasn't fetched it, we shouldn't dump again.
4996                  */
4997                 mutex_exit(&qlt->qlt_ioctl_lock);
4998                 EL(qlt, "qlt_ioctl_flags=%xh, already done\n",
4999                     qlt->qlt_ioctl_flags);
5000                 cmn_err(CE_NOTE, "qlt(%d): Skipping firmware dump as there "
5001                     "is one already outstanding.", qlt->instance);
5002                 return (FCT_FAILURE);
5003         }
5004         qlt->qlt_ioctl_flags |= QLT_FWDUMP_INPROGRESS;
5005         if (ssci->st_rflags & STMF_RFLAG_USER_REQUEST) {
5006                 qlt->qlt_ioctl_flags |= QLT_FWDUMP_TRIGGERED_BY_USER;
5007         } else {
5008                 qlt->qlt_ioctl_flags &= ~QLT_FWDUMP_TRIGGERED_BY_USER;
5009         }
5010         mutex_exit(&qlt->qlt_ioctl_lock);
5011 
5012         size_left = QLT_FWDUMP_BUFSIZE;
5013         if (!qlt->qlt_fwdump_buf) {
5014                 ASSERT(!(qlt->qlt_ioctl_flags & QLT_FWDUMP_ISVALID));
5015                 /*
5016                  * It's the only place that we allocate buf for dumping. After
5017                  * it's allocated, we will use it until the port is detached.
5018                  */
5019                 qlt->qlt_fwdump_buf = kmem_zalloc(size_left, KM_SLEEP);
5020         }
5021 
5022         /*
5023          * Start to dump firmware
5024          */
5025         buf = (caddr_t)qlt->qlt_fwdump_buf;
5026 
5027         /*
5028          * Print the ISP firmware revision number and attributes information
5029          * Read the RISC to Host Status register
5030          */
5031         n = (int)snprintf(buf, size_left, "ISP FW Version %d.%02d.%02d "
5032             "Attributes %04x\n\nR2H Status Register\n%08x",
5033             qlt->fw_major, qlt->fw_minor,
5034             qlt->fw_subminor, qlt->fw_attr, REG_RD32(qlt, REG_RISC_STATUS));
5035         buf += n; size_left -= n;
5036 
5037         /*
5038          * Before pausing the RISC, make sure no mailbox can execute
5039          */
5040         mutex_enter(&qlt->mbox_lock);
5041         if (qlt->mbox_io_state != MBOX_STATE_UNKNOWN) {
5042                 /*
5043                  * Wait to grab the mailboxes
5044                  */
5045                 for (retries = 0; (qlt->mbox_io_state != MBOX_STATE_READY) &&
5046                     (qlt->mbox_io_state != MBOX_STATE_UNKNOWN); retries++) {
5047                         (void) cv_timedwait(&qlt->mbox_cv, &qlt->mbox_lock,
5048                             ddi_get_lbolt() + drv_usectohz(1000000));
5049                         if (retries > 5) {
5050                                 mutex_exit(&qlt->mbox_lock);
5051                                 EL(qlt, "can't drain out mailbox commands\n");
5052                                 goto dump_fail;
5053                         }
5054                 }
5055                 qlt->mbox_io_state = MBOX_STATE_UNKNOWN;
5056                 cv_broadcast(&qlt->mbox_cv);
5057         }
5058         mutex_exit(&qlt->mbox_lock);
5059 
5060         /*
5061          * Pause the RISC processor
5062          */
5063         REG_WR32(qlt, REG_HCCR, HCCR_CMD(SET_RISC_PAUSE));
5064 
5065         /*
5066          * Wait for the RISC processor to pause
5067          */
5068         for (i = 0; i < 200; i++) {
5069                 if (REG_RD32(qlt, REG_RISC_STATUS) & 0x100) {
5070                         break;
5071                 }
5072                 drv_usecwait(1000);
5073         }
5074         if (i == 200) {
5075                 EL(qlt, "can't pause\n");
5076                 return (FCT_FAILURE);
5077         }
5078 
5079         if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip)) {
5080                 goto over_25xx_specific_dump;
5081         }
5082         n = (int)snprintf(buf, size_left, "\n\nHostRisc registers\n");
5083         buf += n; size_left -= n;
5084         REG_WR32(qlt, 0x54, 0x7000);
5085         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5086         buf += n; size_left -= n;
5087         REG_WR32(qlt, 0x54, 0x7010);
5088         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5089         buf += n; size_left -= n;
5090         REG_WR32(qlt, 0x54, 0x7C00);
5091 
5092         n = (int)snprintf(buf, size_left, "\nPCIe registers\n");
5093         buf += n; size_left -= n;
5094         REG_WR32(qlt, 0xC0, 0x1);
5095         n = qlt_fwdump_dump_regs(qlt, buf, 0xc4, 3, size_left);
5096         buf += n; size_left -= n;
5097         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 1, size_left);
5098         buf += n; size_left -= n;
5099         REG_WR32(qlt, 0xC0, 0x0);
5100 
5101 over_25xx_specific_dump:;
5102         n = (int)snprintf(buf, size_left, "\n\nHost Interface Registers\n");
5103         buf += n; size_left -= n;
5104         /*
5105          * Capture data from 32 regsiters
5106          */
5107         n = qlt_fwdump_dump_regs(qlt, buf, 0, 32, size_left);
5108         buf += n; size_left -= n;
5109 
5110         /*
5111          * Disable interrupts
5112          */
5113         REG_WR32(qlt, 0xc, 0);
5114 
5115         /*
5116          * Shadow registers
5117          */
5118         n = (int)snprintf(buf, size_left, "\nShadow Registers\n");
5119         buf += n; size_left -= n;
5120 
5121         REG_WR32(qlt, 0x54, 0xF70);
5122         addr = 0xb0000000;
5123         for (i = 0; i < 0xb; i++) {
5124                 if ((!qlt->qlt_25xx_chip) &&
5125                     (!qlt->qlt_81xx_chip) &&
5126                     (i >= 7)) {
5127                         break;
5128                 }
5129                 if (i && ((i & 7) == 0)) {
5130                         n = (int)snprintf(buf, size_left, "\n");
5131                         buf += n; size_left -= n;
5132                 }
5133                 REG_WR32(qlt, 0xF0, addr);
5134                 n = (int)snprintf(buf, size_left, "%08x ", REG_RD32(qlt, 0xFC));
5135                 buf += n; size_left -= n;
5136                 addr += 0x100000;
5137         }
5138 
5139         if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
5140                 REG_WR32(qlt, 0x54, 0x10);
5141                 n = (int)snprintf(buf, size_left,
5142                     "\n\nRISC IO Register\n%08x", REG_RD32(qlt, 0xC0));
5143                 buf += n; size_left -= n;
5144         }
5145 
5146         /*
5147          * Mailbox registers
5148          */
5149         n = (int)snprintf(buf, size_left, "\n\nMailbox Registers\n");
5150         buf += n; size_left -= n;
5151         for (i = 0; i < 32; i += 2) {
5152                 if ((i + 2) & 15) {
5153                         c = ' ';
5154                 } else {
5155                         c = '\n';
5156                 }
5157                 n = (int)snprintf(buf, size_left, "%04x %04x%c",
5158                     REG_RD16(qlt, 0x80 + (i << 1)),
5159                     REG_RD16(qlt, 0x80 + ((i+1) << 1)), c);
5160                 buf += n; size_left -= n;
5161         }
5162 
5163         /*
5164          * Transfer sequence registers
5165          */
5166         n = (int)snprintf(buf, size_left, "\nXSEQ GP Registers\n");
5167         buf += n; size_left -= n;
5168 
5169         REG_WR32(qlt, 0x54, 0xBF00);
5170         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5171         buf += n; size_left -= n;
5172         REG_WR32(qlt, 0x54, 0xBF10);
5173         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5174         buf += n; size_left -= n;
5175         REG_WR32(qlt, 0x54, 0xBF20);
5176         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5177         buf += n; size_left -= n;
5178         REG_WR32(qlt, 0x54, 0xBF30);
5179         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5180         buf += n; size_left -= n;
5181         REG_WR32(qlt, 0x54, 0xBF40);
5182         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5183         buf += n; size_left -= n;
5184         REG_WR32(qlt, 0x54, 0xBF50);
5185         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5186         buf += n; size_left -= n;
5187         REG_WR32(qlt, 0x54, 0xBF60);
5188         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5189         buf += n; size_left -= n;
5190         REG_WR32(qlt, 0x54, 0xBF70);
5191         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5192         buf += n; size_left -= n;
5193         n = (int)snprintf(buf, size_left, "\nXSEQ-0 registers\n");
5194         buf += n; size_left -= n;
5195         if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
5196                 REG_WR32(qlt, 0x54, 0xBFC0);
5197                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5198                 buf += n; size_left -= n;
5199                 REG_WR32(qlt, 0x54, 0xBFD0);
5200                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5201                 buf += n; size_left -= n;
5202         }
5203         REG_WR32(qlt, 0x54, 0xBFE0);
5204         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5205         buf += n; size_left -= n;
5206         n = (int)snprintf(buf, size_left, "\nXSEQ-1 registers\n");
5207         buf += n; size_left -= n;
5208         REG_WR32(qlt, 0x54, 0xBFF0);
5209         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5210         buf += n; size_left -= n;
5211 
5212         /*
5213          * Receive sequence registers
5214          */
5215         n = (int)snprintf(buf, size_left, "\nRSEQ GP Registers\n");
5216         buf += n; size_left -= n;
5217         REG_WR32(qlt, 0x54, 0xFF00);
5218         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5219         buf += n; size_left -= n;
5220         REG_WR32(qlt, 0x54, 0xFF10);
5221         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5222         buf += n; size_left -= n;
5223         REG_WR32(qlt, 0x54, 0xFF20);
5224         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5225         buf += n; size_left -= n;
5226         REG_WR32(qlt, 0x54, 0xFF30);
5227         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5228         buf += n; size_left -= n;
5229         REG_WR32(qlt, 0x54, 0xFF40);
5230         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5231         buf += n; size_left -= n;
5232         REG_WR32(qlt, 0x54, 0xFF50);
5233         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5234         buf += n; size_left -= n;
5235         REG_WR32(qlt, 0x54, 0xFF60);
5236         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5237         buf += n; size_left -= n;
5238         REG_WR32(qlt, 0x54, 0xFF70);
5239         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5240         buf += n; size_left -= n;
5241         n = (int)snprintf(buf, size_left, "\nRSEQ-0 registers\n");
5242         buf += n; size_left -= n;
5243         if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
5244                 REG_WR32(qlt, 0x54, 0xFFC0);
5245                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5246                 buf += n; size_left -= n;
5247         }
5248         REG_WR32(qlt, 0x54, 0xFFD0);
5249         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5250         buf += n; size_left -= n;
5251         n = (int)snprintf(buf, size_left, "\nRSEQ-1 registers\n");
5252         buf += n; size_left -= n;
5253         REG_WR32(qlt, 0x54, 0xFFE0);
5254         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5255         buf += n; size_left -= n;
5256         n = (int)snprintf(buf, size_left, "\nRSEQ-2 registers\n");
5257         buf += n; size_left -= n;
5258         REG_WR32(qlt, 0x54, 0xFFF0);
5259         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5260         buf += n; size_left -= n;
5261 
5262         if ((!qlt->qlt_25xx_chip) && (!qlt->qlt_81xx_chip))
5263                 goto over_aseq_regs;
5264 
5265         /*
5266          * Auxiliary sequencer registers
5267          */
5268         n = (int)snprintf(buf, size_left, "\nASEQ GP Registers\n");
5269         buf += n; size_left -= n;
5270         REG_WR32(qlt, 0x54, 0xB000);
5271         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5272         buf += n; size_left -= n;
5273         REG_WR32(qlt, 0x54, 0xB010);
5274         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5275         buf += n; size_left -= n;
5276         REG_WR32(qlt, 0x54, 0xB020);
5277         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5278         buf += n; size_left -= n;
5279         REG_WR32(qlt, 0x54, 0xB030);
5280         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5281         buf += n; size_left -= n;
5282         REG_WR32(qlt, 0x54, 0xB040);
5283         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5284         buf += n; size_left -= n;
5285         REG_WR32(qlt, 0x54, 0xB050);
5286         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5287         buf += n; size_left -= n;
5288         REG_WR32(qlt, 0x54, 0xB060);
5289         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5290         buf += n; size_left -= n;
5291         REG_WR32(qlt, 0x54, 0xB070);
5292         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5293         buf += n; size_left -= n;
5294         n = (int)snprintf(buf, size_left, "\nASEQ-0 registers\n");
5295         buf += n; size_left -= n;
5296         REG_WR32(qlt, 0x54, 0xB0C0);
5297         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5298         buf += n; size_left -= n;
5299         REG_WR32(qlt, 0x54, 0xB0D0);
5300         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5301         buf += n; size_left -= n;
5302         n = (int)snprintf(buf, size_left, "\nASEQ-1 registers\n");
5303         buf += n; size_left -= n;
5304         REG_WR32(qlt, 0x54, 0xB0E0);
5305         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5306         buf += n; size_left -= n;
5307         n = (int)snprintf(buf, size_left, "\nASEQ-2 registers\n");
5308         buf += n; size_left -= n;
5309         REG_WR32(qlt, 0x54, 0xB0F0);
5310         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5311         buf += n; size_left -= n;
5312 
5313 over_aseq_regs:;
5314 
5315         /*
5316          * Command DMA registers
5317          */
5318         n = (int)snprintf(buf, size_left, "\nCommand DMA registers\n");
5319         buf += n; size_left -= n;
5320         REG_WR32(qlt, 0x54, 0x7100);
5321         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5322         buf += n; size_left -= n;
5323 
5324         /*
5325          * Queues
5326          */
5327         n = (int)snprintf(buf, size_left,
5328             "\nRequest0 Queue DMA Channel registers\n");
5329         buf += n; size_left -= n;
5330         REG_WR32(qlt, 0x54, 0x7200);
5331         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left);
5332         buf += n; size_left -= n;
5333         n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left);
5334         buf += n; size_left -= n;
5335 
5336         n = (int)snprintf(buf, size_left,
5337             "\n\nResponse0 Queue DMA Channel registers\n");
5338         buf += n; size_left -= n;
5339         REG_WR32(qlt, 0x54, 0x7300);
5340         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left);
5341         buf += n; size_left -= n;
5342         n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left);
5343         buf += n; size_left -= n;
5344 
5345         n = (int)snprintf(buf, size_left,
5346             "\n\nRequest1 Queue DMA Channel registers\n");
5347         buf += n; size_left -= n;
5348         REG_WR32(qlt, 0x54, 0x7400);
5349         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 8, size_left);
5350         buf += n; size_left -= n;
5351         n = qlt_fwdump_dump_regs(qlt, buf, 0xe4, 7, size_left);
5352         buf += n; size_left -= n;
5353 
5354         /*
5355          * Transmit DMA registers
5356          */
5357         n = (int)snprintf(buf, size_left, "\n\nXMT0 Data DMA registers\n");
5358         buf += n; size_left -= n;
5359         REG_WR32(qlt, 0x54, 0x7600);
5360         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5361         buf += n; size_left -= n;
5362         REG_WR32(qlt, 0x54, 0x7610);
5363         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5364         buf += n; size_left -= n;
5365         n = (int)snprintf(buf, size_left, "\nXMT1 Data DMA registers\n");
5366         buf += n; size_left -= n;
5367         REG_WR32(qlt, 0x54, 0x7620);
5368         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5369         buf += n; size_left -= n;
5370         REG_WR32(qlt, 0x54, 0x7630);
5371         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5372         buf += n; size_left -= n;
5373         n = (int)snprintf(buf, size_left, "\nXMT2 Data DMA registers\n");
5374         buf += n; size_left -= n;
5375         REG_WR32(qlt, 0x54, 0x7640);
5376         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5377         buf += n; size_left -= n;
5378         REG_WR32(qlt, 0x54, 0x7650);
5379         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5380         buf += n; size_left -= n;
5381         n = (int)snprintf(buf, size_left, "\nXMT3 Data DMA registers\n");
5382         buf += n; size_left -= n;
5383         REG_WR32(qlt, 0x54, 0x7660);
5384         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5385         buf += n; size_left -= n;
5386         REG_WR32(qlt, 0x54, 0x7670);
5387         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5388         buf += n; size_left -= n;
5389         n = (int)snprintf(buf, size_left, "\nXMT4 Data DMA registers\n");
5390         buf += n; size_left -= n;
5391         REG_WR32(qlt, 0x54, 0x7680);
5392         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5393         buf += n; size_left -= n;
5394         REG_WR32(qlt, 0x54, 0x7690);
5395         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5396         buf += n; size_left -= n;
5397         n = (int)snprintf(buf, size_left, "\nXMT Data DMA Common registers\n");
5398         buf += n; size_left -= n;
5399         REG_WR32(qlt, 0x54, 0x76A0);
5400         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5401         buf += n; size_left -= n;
5402 
5403         /*
5404          * Receive DMA registers
5405          */
5406         n = (int)snprintf(buf, size_left,
5407             "\nRCV Thread 0 Data DMA registers\n");
5408         buf += n; size_left -= n;
5409         REG_WR32(qlt, 0x54, 0x7700);
5410         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5411         buf += n; size_left -= n;
5412         REG_WR32(qlt, 0x54, 0x7710);
5413         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5414         buf += n; size_left -= n;
5415         n = (int)snprintf(buf, size_left,
5416             "\nRCV Thread 1 Data DMA registers\n");
5417         buf += n; size_left -= n;
5418         REG_WR32(qlt, 0x54, 0x7720);
5419         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5420         buf += n; size_left -= n;
5421         REG_WR32(qlt, 0x54, 0x7730);
5422         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5423         buf += n; size_left -= n;
5424 
5425         /*
5426          * RISC registers
5427          */
5428         n = (int)snprintf(buf, size_left, "\nRISC GP registers\n");
5429         buf += n; size_left -= n;
5430         REG_WR32(qlt, 0x54, 0x0F00);
5431         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5432         buf += n; size_left -= n;
5433         REG_WR32(qlt, 0x54, 0x0F10);
5434         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5435         buf += n; size_left -= n;
5436         REG_WR32(qlt, 0x54, 0x0F20);
5437         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5438         buf += n; size_left -= n;
5439         REG_WR32(qlt, 0x54, 0x0F30);
5440         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5441         buf += n; size_left -= n;
5442         REG_WR32(qlt, 0x54, 0x0F40);
5443         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5444         buf += n; size_left -= n;
5445         REG_WR32(qlt, 0x54, 0x0F50);
5446         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5447         buf += n; size_left -= n;
5448         REG_WR32(qlt, 0x54, 0x0F60);
5449         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5450         buf += n; size_left -= n;
5451         REG_WR32(qlt, 0x54, 0x0F70);
5452         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5453         buf += n; size_left -= n;
5454 
5455         /*
5456          * Local memory controller registers
5457          */
5458         n = (int)snprintf(buf, size_left, "\nLMC registers\n");
5459         buf += n; size_left -= n;
5460         REG_WR32(qlt, 0x54, 0x3000);
5461         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5462         buf += n; size_left -= n;
5463         REG_WR32(qlt, 0x54, 0x3010);
5464         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5465         buf += n; size_left -= n;
5466         REG_WR32(qlt, 0x54, 0x3020);
5467         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5468         buf += n; size_left -= n;
5469         REG_WR32(qlt, 0x54, 0x3030);
5470         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5471         buf += n; size_left -= n;
5472         REG_WR32(qlt, 0x54, 0x3040);
5473         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5474         buf += n; size_left -= n;
5475         REG_WR32(qlt, 0x54, 0x3050);
5476         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5477         buf += n; size_left -= n;
5478         REG_WR32(qlt, 0x54, 0x3060);
5479         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5480         buf += n; size_left -= n;
5481 
5482         if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
5483                 REG_WR32(qlt, 0x54, 0x3070);
5484                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5485                 buf += n; size_left -= n;
5486         }
5487 
5488         /*
5489          * Fibre protocol module regsiters
5490          */
5491         n = (int)snprintf(buf, size_left, "\nFPM hardware registers\n");
5492         buf += n; size_left -= n;
5493         REG_WR32(qlt, 0x54, 0x4000);
5494         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5495         buf += n; size_left -= n;
5496         REG_WR32(qlt, 0x54, 0x4010);
5497         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5498         buf += n; size_left -= n;
5499         REG_WR32(qlt, 0x54, 0x4020);
5500         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5501         buf += n; size_left -= n;
5502         REG_WR32(qlt, 0x54, 0x4030);
5503         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5504         buf += n; size_left -= n;
5505         REG_WR32(qlt, 0x54, 0x4040);
5506         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5507         buf += n; size_left -= n;
5508         REG_WR32(qlt, 0x54, 0x4050);
5509         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5510         buf += n; size_left -= n;
5511         REG_WR32(qlt, 0x54, 0x4060);
5512         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5513         buf += n; size_left -= n;
5514         REG_WR32(qlt, 0x54, 0x4070);
5515         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5516         buf += n; size_left -= n;
5517         REG_WR32(qlt, 0x54, 0x4080);
5518         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5519         buf += n; size_left -= n;
5520         REG_WR32(qlt, 0x54, 0x4090);
5521         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5522         buf += n; size_left -= n;
5523         REG_WR32(qlt, 0x54, 0x40A0);
5524         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5525         buf += n; size_left -= n;
5526         REG_WR32(qlt, 0x54, 0x40B0);
5527         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5528         buf += n; size_left -= n;
5529         if (qlt->qlt_81xx_chip) {
5530                 REG_WR32(qlt, 0x54, 0x40C0);
5531                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5532                 buf += n; size_left -= n;
5533                 REG_WR32(qlt, 0x54, 0x40D0);
5534                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5535                 buf += n; size_left -= n;
5536         }
5537 
5538         /*
5539          * Fibre buffer registers
5540          */
5541         n = (int)snprintf(buf, size_left, "\nFB hardware registers\n");
5542         buf += n; size_left -= n;
5543         REG_WR32(qlt, 0x54, 0x6000);
5544         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5545         buf += n; size_left -= n;
5546         REG_WR32(qlt, 0x54, 0x6010);
5547         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5548         buf += n; size_left -= n;
5549         REG_WR32(qlt, 0x54, 0x6020);
5550         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5551         buf += n; size_left -= n;
5552         REG_WR32(qlt, 0x54, 0x6030);
5553         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5554         buf += n; size_left -= n;
5555         REG_WR32(qlt, 0x54, 0x6040);
5556         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5557         buf += n; size_left -= n;
5558         REG_WR32(qlt, 0x54, 0x6100);
5559         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5560         buf += n; size_left -= n;
5561         REG_WR32(qlt, 0x54, 0x6130);
5562         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5563         buf += n; size_left -= n;
5564         REG_WR32(qlt, 0x54, 0x6150);
5565         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5566         buf += n; size_left -= n;
5567         REG_WR32(qlt, 0x54, 0x6170);
5568         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5569         buf += n; size_left -= n;
5570         REG_WR32(qlt, 0x54, 0x6190);
5571         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5572         buf += n; size_left -= n;
5573         REG_WR32(qlt, 0x54, 0x61B0);
5574         n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5575         buf += n; size_left -= n;
5576         if (qlt->qlt_81xx_chip) {
5577                 REG_WR32(qlt, 0x54, 0x61C0);
5578                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5579                 buf += n; size_left -= n;
5580         }
5581         if ((qlt->qlt_25xx_chip) || (qlt->qlt_81xx_chip)) {
5582                 REG_WR32(qlt, 0x54, 0x6F00);
5583                 n = qlt_fwdump_dump_regs(qlt, buf, 0xc0, 16, size_left);
5584                 buf += n; size_left -= n;
5585         }
5586 
5587         qlt->intr_sneak_counter = 10;
5588         mutex_enter(&qlt->intr_lock);
5589         (void) qlt_reset_chip(qlt);
5590         drv_usecwait(20);
5591         qlt->intr_sneak_counter = 0;
5592         mutex_exit(&qlt->intr_lock);
5593 
5594         /*
5595          * Memory
5596          */
5597         n = (int)snprintf(buf, size_left, "\nCode RAM\n");
5598         buf += n; size_left -= n;
5599 
5600         addr = 0x20000;
5601         endaddr = 0x22000;
5602         words_to_read = 0;
5603         while (addr < endaddr) {
5604                 words_to_read = MBOX_DMA_MEM_SIZE >> 2;
5605                 if ((words_to_read + addr) > endaddr) {
5606                         words_to_read = endaddr - addr;
5607                 }
5608                 if ((ret = qlt_read_risc_ram(qlt, addr, words_to_read)) !=
5609                     QLT_SUCCESS) {
5610                         EL(qlt, "Error reading risc ram - CODE RAM status="
5611                             "%llxh\n", ret);
5612                         goto dump_fail;
5613                 }
5614 
5615                 n = qlt_dump_risc_ram(qlt, addr, words_to_read, buf, size_left);
5616                 buf += n; size_left -= n;
5617 
5618                 if (size_left < 100000) {
5619                         EL(qlt, "run out of space - CODE RAM size_left=%d\n",
5620                             size_left);
5621                         goto dump_ok;
5622                 }
5623                 addr += words_to_read;
5624         }
5625 
5626         n = (int)snprintf(buf, size_left, "\nExternal Memory\n");
5627         buf += n; size_left -= n;
5628 
5629         addr = 0x100000;
5630         endaddr = (((uint32_t)(qlt->fw_endaddrhi)) << 16) | qlt->fw_endaddrlo;
5631         endaddr++;
5632         if (endaddr & 7) {
5633                 endaddr = (endaddr + 7) & 0xFFFFFFF8;
5634         }
5635 
5636         words_to_read = 0;
5637         while (addr < endaddr) {
5638                 words_to_read = MBOX_DMA_MEM_SIZE >> 2;
5639                 if ((words_to_read + addr) > endaddr) {
5640                         words_to_read = endaddr - addr;
5641                 }
5642                 if ((ret = qlt_read_risc_ram(qlt, addr, words_to_read)) !=
5643                     QLT_SUCCESS) {
5644                         EL(qlt, "Error reading risc ram - EXT RAM status="
5645                             "%llxh\n", ret);
5646                         goto dump_fail;
5647                 }
5648                 n = qlt_dump_risc_ram(qlt, addr, words_to_read, buf, size_left);
5649                 buf += n; size_left -= n;
5650                 if (size_left < 100000) {
5651                         EL(qlt, "run out of space - EXT RAM\n");
5652                         goto dump_ok;
5653                 }
5654                 addr += words_to_read;
5655         }
5656 
5657         /*
5658          * Label the end tag
5659          */
5660         n = (int)snprintf(buf, size_left, "[<==END] ISP Debug Dump\n");
5661         buf += n; size_left -= n;
5662 
5663         /*
5664          * Queue dumping
5665          */
5666         n = (int)snprintf(buf, size_left, "\nRequest Queue\n");
5667         buf += n; size_left -= n;
5668         n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + REQUEST_QUEUE_OFFSET,
5669             REQUEST_QUEUE_ENTRIES, buf, size_left);
5670         buf += n; size_left -= n;
5671 
5672         n = (int)snprintf(buf, size_left, "\nPriority Queue\n");
5673         buf += n; size_left -= n;
5674         n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + PRIORITY_QUEUE_OFFSET,
5675             PRIORITY_QUEUE_ENTRIES, buf, size_left);
5676         buf += n; size_left -= n;
5677 
5678         n = (int)snprintf(buf, size_left, "\nResponse Queue\n");
5679         buf += n; size_left -= n;
5680         n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + RESPONSE_QUEUE_OFFSET,
5681             RESPONSE_QUEUE_ENTRIES, buf, size_left);
5682         buf += n; size_left -= n;
5683 
5684         n = (int)snprintf(buf, size_left, "\nATIO queue\n");
5685         buf += n; size_left -= n;
5686         n = qlt_dump_queue(qlt, qlt->queue_mem_ptr + ATIO_QUEUE_OFFSET,
5687             ATIO_QUEUE_ENTRIES, buf, size_left);
5688         buf += n; size_left -= n;
5689 
5690         /*
5691          * Label dump reason
5692          */
5693         n = (int)snprintf(buf, size_left, "\nFirmware dump reason: %s-%s\n",
5694             qlt->qlt_port_alias, ssci->st_additional_info);
5695         buf += n; size_left -= n;
5696 
5697 dump_ok:
5698         EL(qlt, "left-%d\n", size_left);
5699 
5700         mutex_enter(&qlt->qlt_ioctl_lock);
5701         qlt->qlt_ioctl_flags &=
5702             ~(QLT_FWDUMP_INPROGRESS | QLT_FWDUMP_FETCHED_BY_USER);
5703         qlt->qlt_ioctl_flags |= QLT_FWDUMP_ISVALID;
5704         mutex_exit(&qlt->qlt_ioctl_lock);
5705         return (FCT_SUCCESS);
5706 
5707 dump_fail:
5708         EL(qlt, "dump not done\n");
5709         mutex_enter(&qlt->qlt_ioctl_lock);
5710         qlt->qlt_ioctl_flags &= QLT_IOCTL_FLAG_MASK;
5711         mutex_exit(&qlt->qlt_ioctl_lock);
5712         return (FCT_FAILURE);
5713 }
5714 
5715 static int
5716 qlt_fwdump_dump_regs(qlt_state_t *qlt, caddr_t buf, int startaddr, int count,
5717     uint_t size_left)
5718 {
5719         int             i;
5720         int             n;
5721         char            c = ' ';
5722 
5723         for (i = 0, n = 0; i < count; i++) {
5724                 if ((i + 1) & 7) {
5725                         c = ' ';
5726                 } else {
5727                         c = '\n';
5728                 }
5729                 n = (int)(n + (int)snprintf(&buf[n], (uint_t)(size_left - n),
5730                     "%08x%c", REG_RD32(qlt, startaddr + (i << 2)), c));
5731         }
5732         return (n);
5733 }
5734 
5735 static int
5736 qlt_dump_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words,
5737     caddr_t buf, uint_t size_left)
5738 {
5739         int             i;
5740         int             n;
5741         char            c = ' ';
5742         uint32_t        *ptr;
5743 
5744         ptr = (uint32_t *)((caddr_t)qlt->queue_mem_ptr + MBOX_DMA_MEM_OFFSET);
5745         for (i = 0, n = 0; i < words; i++) {
5746                 if ((i & 7) == 0) {
5747                         n = (int)(n + (int)snprintf(&buf[n],
5748                             (uint_t)(size_left - n), "%08x: ", addr + i));
5749                 }
5750                 if ((i + 1) & 7) {
5751                         c = ' ';
5752                 } else {
5753                         c = '\n';
5754                 }
5755                 n = (int)(n + (int)snprintf(&buf[n], (uint_t)(size_left - n),
5756                     "%08x%c", ptr[i], c));
5757         }
5758         return (n);
5759 }
5760 
5761 static int
5762 qlt_dump_queue(qlt_state_t *qlt, caddr_t qadr, int entries, caddr_t buf,
5763     uint_t size_left)
5764 {
5765         int             i;
5766         int             n;
5767         char            c = ' ';
5768         int             words;
5769         uint16_t        *ptr;
5770         uint16_t        w;
5771 
5772         words = entries * 32;
5773         ptr = (uint16_t *)qadr;
5774         for (i = 0, n = 0; i < words; i++) {
5775                 if ((i & 7) == 0) {
5776                         n = (int)(n + (int)snprintf(&buf[n],
5777                             (uint_t)(size_left - n), "%05x: ", i));
5778                 }
5779                 if ((i + 1) & 7) {
5780                         c = ' ';
5781                 } else {
5782                         c = '\n';
5783                 }
5784                 w = QMEM_RD16(qlt, &ptr[i]);
5785                 n = (int)(n + (int)snprintf(&buf[n], (size_left - n), "%04x%c",
5786                     w, c));
5787         }
5788         return (n);
5789 }
5790 
5791 /*
5792  * Only called by debug dump. Interrupts are disabled and mailboxes alongwith
5793  * mailbox ram is available.
5794  * Copy data from RISC RAM to system memory
5795  */
5796 static fct_status_t
5797 qlt_read_risc_ram(qlt_state_t *qlt, uint32_t addr, uint32_t words)
5798 {
5799         uint64_t        da;
5800         fct_status_t    ret;
5801 
5802         REG_WR16(qlt, REG_MBOX(0), MBC_DUMP_RAM_EXTENDED);
5803         da = qlt->queue_mem_cookie.dmac_laddress;
5804         da += MBOX_DMA_MEM_OFFSET;
5805 
5806         /* System destination address */
5807         REG_WR16(qlt, REG_MBOX(3), LSW(LSD(da)));
5808         REG_WR16(qlt, REG_MBOX(2), MSW(LSD(da)));
5809         REG_WR16(qlt, REG_MBOX(7), LSW(MSD(da)));
5810         REG_WR16(qlt, REG_MBOX(6), MSW(MSD(da)));
5811 
5812         /* Length */
5813         REG_WR16(qlt, REG_MBOX(5), LSW(words));
5814         REG_WR16(qlt, REG_MBOX(4), MSW(words));
5815 
5816         /* RISC source address */
5817         REG_WR16(qlt, REG_MBOX(1), LSW(addr));
5818         REG_WR16(qlt, REG_MBOX(8), MSW(addr));
5819 
5820         ret = qlt_raw_mailbox_command(qlt);
5821         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
5822         if (ret == QLT_SUCCESS) {
5823                 (void) ddi_dma_sync(qlt->queue_mem_dma_handle,
5824                     MBOX_DMA_MEM_OFFSET, words << 2, DDI_DMA_SYNC_FORCPU);
5825         } else {
5826                 EL(qlt, "qlt_raw_mailbox_command=ch status=%llxh\n", ret);
5827         }
5828         return (ret);
5829 }
5830 
5831 static void
5832 qlt_verify_fw(qlt_state_t *qlt)
5833 {
5834         caddr_t req;
5835         /* Just put it on the request queue */
5836         mutex_enter(&qlt->req_lock);
5837         req = qlt_get_req_entries(qlt, 1);
5838         if (req == NULL) {
5839                 mutex_exit(&qlt->req_lock);
5840                 /* XXX handle this */
5841                 return;
5842         }
5843 
5844         bzero(req, IOCB_SIZE);
5845 
5846         req[0] = 0x1b;
5847         req[1] = 1;
5848 
5849         QMEM_WR32(qlt, (&req[4]), 0xffffffff);
5850         QMEM_WR16(qlt, (&req[0x8]), 1);    /*  options - don't update */
5851         QMEM_WR32(qlt, (&req[0x14]), 0x80010300);
5852 
5853         qlt_submit_req_entries(qlt, 1);
5854         mutex_exit(&qlt->req_lock);
5855 }
5856 
5857 static void
5858 qlt_handle_verify_fw_completion(qlt_state_t *qlt, uint8_t *rsp)
5859 {
5860         uint16_t        status;
5861         char            info[QLT_INFO_LEN];
5862 
5863         status = QMEM_RD16(qlt, rsp+8);
5864         if (status != 0) {
5865                 (void) snprintf(info, sizeof (info),
5866                     "qlt_handle_verify_fw_completion: "
5867                     "status:%x, rsp:%p", status, (void *)rsp);
5868                 if (status == 3) {
5869                         uint16_t error_code;
5870 
5871                         error_code = QMEM_RD16(qlt, rsp+0xA);
5872                         (void) snprintf(info, sizeof (info),
5873                             "qlt_handle_verify_fw_completion: error code:%x",
5874                             error_code);
5875                 }
5876         }
5877 }
5878 
5879 /*
5880  * qlt_el_trace_desc_ctor - Construct an extended logging trace descriptor.
5881  *
5882  * Input:       Pointer to the adapter state structure.
5883  * Returns:     Success or Failure.
5884  * Context:     Kernel context.
5885  */
5886 static int
5887 qlt_el_trace_desc_ctor(qlt_state_t *qlt)
5888 {
5889         int     rval = DDI_SUCCESS;
5890 
5891         qlt->el_trace_desc = (qlt_el_trace_desc_t *)
5892             kmem_zalloc(sizeof (qlt_el_trace_desc_t), KM_SLEEP);
5893 
5894         if (qlt->el_trace_desc == NULL) {
5895                 cmn_err(CE_WARN, "qlt(%d): can't construct trace descriptor",
5896                     qlt->instance);
5897                 rval = DDI_FAILURE;
5898         } else {
5899                 qlt->el_trace_desc->next = 0;
5900                 qlt->el_trace_desc->trace_buffer =
5901                     (char *)kmem_zalloc(EL_TRACE_BUF_SIZE, KM_SLEEP);
5902 
5903                 if (qlt->el_trace_desc->trace_buffer == NULL) {
5904                         cmn_err(CE_WARN, "qlt(%d): can't get trace buffer",
5905                             qlt->instance);
5906                         kmem_free(qlt->el_trace_desc,
5907                             sizeof (qlt_el_trace_desc_t));
5908                         qlt->el_trace_desc = NULL;
5909                         rval = DDI_FAILURE;
5910                 } else {
5911                         qlt->el_trace_desc->trace_buffer_size =
5912                             EL_TRACE_BUF_SIZE;
5913                         mutex_init(&qlt->el_trace_desc->mutex, NULL,
5914                             MUTEX_DRIVER, NULL);
5915                 }
5916         }
5917 
5918         return (rval);
5919 }
5920 
5921 /*
5922  * qlt_el_trace_desc_dtor - Destroy an extended logging trace descriptor.
5923  *
5924  * Input:       Pointer to the adapter state structure.
5925  * Returns:     Success or Failure.
5926  * Context:     Kernel context.
5927  */
5928 static int
5929 qlt_el_trace_desc_dtor(qlt_state_t *qlt)
5930 {
5931         int     rval = DDI_SUCCESS;
5932 
5933         if (qlt->el_trace_desc == NULL) {
5934                 cmn_err(CE_WARN, "qlt(%d): can't destroy el trace descriptor",
5935                     qlt->instance);
5936                 rval = DDI_FAILURE;
5937         } else {
5938                 if (qlt->el_trace_desc->trace_buffer != NULL) {
5939                         kmem_free(qlt->el_trace_desc->trace_buffer,
5940                             qlt->el_trace_desc->trace_buffer_size);
5941                 }
5942                 mutex_destroy(&qlt->el_trace_desc->mutex);
5943                 kmem_free(qlt->el_trace_desc, sizeof (qlt_el_trace_desc_t));
5944                 qlt->el_trace_desc = NULL;
5945         }
5946 
5947         return (rval);
5948 }
5949 
5950 /*
5951  * qlt_el_msg
5952  *      Extended logging message
5953  *
5954  * Input:
5955  *      qlt:    adapter state pointer.
5956  *      fn:     function name.
5957  *      ce:     level
5958  *      ...:    Variable argument list.
5959  *
5960  * Context:
5961  *      Kernel/Interrupt context.
5962  */
5963 void
5964 qlt_el_msg(qlt_state_t *qlt, const char *fn, int ce, ...)
5965 {
5966         char            *s, *fmt = 0, *fmt1 = 0;
5967         char            fmt2[EL_BUFFER_RESERVE];
5968         int             rval, tmp;
5969         int             tracing = 0;
5970         va_list         vl;
5971 
5972         /* Tracing is the default but it can be disabled. */
5973         if ((rval = qlt_validate_trace_desc(qlt)) == DDI_SUCCESS) {
5974                 tracing = 1;
5975 
5976                 mutex_enter(&qlt->el_trace_desc->mutex);
5977 
5978                 /*
5979                  * Ensure enough space for the string. Wrap to
5980                  * start when default message allocation size
5981                  * would overrun the end.
5982                  */
5983                 if ((qlt->el_trace_desc->next + EL_BUFFER_RESERVE) >=
5984                     qlt->el_trace_desc->trace_buffer_size) {
5985                         fmt = qlt->el_trace_desc->trace_buffer;
5986                         qlt->el_trace_desc->next = 0;
5987                 } else {
5988                         fmt = qlt->el_trace_desc->trace_buffer +
5989                             qlt->el_trace_desc->next;
5990                 }
5991         }
5992 
5993         /* if no buffer use the stack */
5994         if (fmt == NULL) {
5995                 fmt = fmt2;
5996         }
5997 
5998         va_start(vl, ce);
5999 
6000         s = va_arg(vl, char *);
6001 
6002         rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
6003             "QEL qlt(%d): %s, ", qlt->instance, fn);
6004         fmt1 = fmt + rval;
6005         tmp = (int)vsnprintf(fmt1,
6006             (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
6007         rval += tmp;
6008 
6009         /*
6010          * Calculate the offset where the next message will go,
6011          * skipping the NULL.
6012          */
6013         if (tracing) {
6014                 uint16_t next = (uint16_t)(rval += 1);
6015                 qlt->el_trace_desc->next += next;
6016                 mutex_exit(&qlt->el_trace_desc->mutex);
6017         }
6018 
6019         if (enable_extended_logging) {
6020                 cmn_err(ce, fmt);
6021         }
6022 
6023         va_end(vl);
6024 }
6025 
6026 /*
6027  * qlt_dump_el_trace_buffer
6028  *       Outputs extended logging trace buffer.
6029  *
6030  * Input:
6031  *      qlt:    adapter state pointer.
6032  */
6033 void
6034 qlt_dump_el_trace_buffer(qlt_state_t *qlt)
6035 {
6036         char            *dump_start = NULL;
6037         char            *dump_current = NULL;
6038         char            *trace_start;
6039         char            *trace_end;
6040         int             wrapped = 0;
6041         int             rval;
6042 
6043         mutex_enter(&qlt->el_trace_desc->mutex);
6044 
6045         rval = qlt_validate_trace_desc(qlt);
6046         if (rval != NULL) {
6047                 cmn_err(CE_CONT, "qlt(%d) Dump EL trace - invalid desc\n",
6048                     qlt->instance);
6049         } else if ((dump_start = qlt_find_trace_start(qlt)) != NULL) {
6050                 dump_current = dump_start;
6051                 trace_start = qlt->el_trace_desc->trace_buffer;
6052                 trace_end = trace_start +
6053                     qlt->el_trace_desc->trace_buffer_size;
6054 
6055                 cmn_err(CE_CONT, "qlt(%d) Dump EL trace - start %p %p\n",
6056                     qlt->instance,
6057                     (void *)dump_start, (void *)trace_start);
6058 
6059                 while (((uintptr_t)dump_current - (uintptr_t)trace_start) <=
6060                     (uintptr_t)qlt->el_trace_desc->trace_buffer_size) {
6061                         /* Show it... */
6062                         cmn_err(CE_CONT, "%p - %s", (void *)dump_current,
6063                             dump_current);
6064                         /* Make the next the current */
6065                         dump_current += (strlen(dump_current) + 1);
6066                         /* check for wrap */
6067                         if ((dump_current + EL_BUFFER_RESERVE) >= trace_end) {
6068                                 dump_current = trace_start;
6069                                 wrapped = 1;
6070                         } else if (wrapped) {
6071                                 /* Don't go past next. */
6072                                 if ((trace_start + qlt->el_trace_desc->next) <=
6073                                     dump_current) {
6074                                         break;
6075                                 }
6076                         } else if (*dump_current == NULL) {
6077                                 break;
6078                         }
6079                 }
6080         }
6081         mutex_exit(&qlt->el_trace_desc->mutex);
6082 }
6083 
6084 /*
6085  * qlt_validate_trace_desc
6086  *       Ensures the extended logging trace descriptor is good.
6087  *
6088  * Input:
6089  *      qlt:    adapter state pointer.
6090  *
6091  * Returns:
6092  *      ql local function return status code.
6093  */
6094 static int
6095 qlt_validate_trace_desc(qlt_state_t *qlt)
6096 {
6097         int     rval = DDI_SUCCESS;
6098 
6099         if (qlt->el_trace_desc == NULL) {
6100                 rval = DDI_FAILURE;
6101         } else if (qlt->el_trace_desc->trace_buffer == NULL) {
6102                 rval = DDI_FAILURE;
6103         }
6104         return (rval);
6105 }
6106 
6107 /*
6108  * qlt_find_trace_start
6109  *       Locate the oldest extended logging trace entry.
6110  *
6111  * Input:
6112  *      qlt:    adapter state pointer.
6113  *
6114  * Returns:
6115  *      Pointer to a string.
6116  *
6117  * Context:
6118  *      Kernel/Interrupt context.
6119  */
6120 static char *
6121 qlt_find_trace_start(qlt_state_t *qlt)
6122 {
6123         char    *trace_start = 0;
6124         char    *trace_next  = 0;
6125 
6126         trace_next = qlt->el_trace_desc->trace_buffer +
6127             qlt->el_trace_desc->next;
6128 
6129         /*
6130          * If the buffer has not wrapped next will point at a null so
6131          * start is the beginning of the buffer.  If next points at a char
6132          * then we must traverse the buffer until a null is detected and
6133          * that will be the beginning of the oldest whole object in the buffer
6134          * which is the start.
6135          */
6136 
6137         if ((trace_next + EL_BUFFER_RESERVE) >=
6138             (qlt->el_trace_desc->trace_buffer +
6139             qlt->el_trace_desc->trace_buffer_size)) {
6140                 trace_start = qlt->el_trace_desc->trace_buffer;
6141         } else if (*trace_next != NULL) {
6142                 trace_start = trace_next + (strlen(trace_next) + 1);
6143         } else {
6144                 trace_start = qlt->el_trace_desc->trace_buffer;
6145         }
6146         return (trace_start);
6147 }
6148 
6149 
6150 static int
6151 qlt_read_int_prop(qlt_state_t *qlt, char *prop, int defval)
6152 {
6153         return (ddi_getprop(DDI_DEV_T_ANY, qlt->dip,
6154             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, prop, defval));
6155 }
6156 
6157 static int
6158 qlt_read_string_prop(qlt_state_t *qlt, char *prop, char **prop_val)
6159 {
6160         return (ddi_prop_lookup_string(DDI_DEV_T_ANY, qlt->dip,
6161             DDI_PROP_DONTPASS, prop, prop_val));
6162 }
6163 
6164 static int
6165 qlt_read_int_instance_prop(qlt_state_t *qlt, char *prop, int defval)
6166 {
6167         char            inst_prop[256];
6168         int             val;
6169 
6170         /*
6171          * Get adapter instance specific parameters. If the instance
6172          * specific parameter isn't there, try the global parameter.
6173          */
6174 
6175         (void) sprintf(inst_prop, "hba%d-%s", qlt->instance, prop);
6176 
6177         if ((val = qlt_read_int_prop(qlt, inst_prop, defval)) == defval) {
6178                 val = qlt_read_int_prop(qlt, prop, defval);
6179         }
6180 
6181         return (val);
6182 }
6183 
6184 static int
6185 qlt_read_string_instance_prop(qlt_state_t *qlt, char *prop, char **prop_val)
6186 {
6187         char            instance_prop[256];
6188 
6189         /* Get adapter instance specific parameter. */
6190         (void) sprintf(instance_prop, "hba%d-%s", qlt->instance, prop);
6191         return (qlt_read_string_prop(qlt, instance_prop, prop_val));
6192 }
6193 
6194 static int
6195 qlt_convert_string_to_ull(char *prop, int radix,
6196     u_longlong_t *result)
6197 {
6198         return (ddi_strtoull((const char *)prop, 0, radix, result));
6199 }
6200 
6201 static boolean_t
6202 qlt_wwn_overload_prop(qlt_state_t *qlt)
6203 {
6204         char            *prop_val = 0;
6205         int             rval;
6206         int             radix;
6207         u_longlong_t    wwnn = 0, wwpn = 0;
6208         boolean_t       overloaded = FALSE;
6209 
6210         radix = 16;
6211 
6212         rval = qlt_read_string_instance_prop(qlt, "adapter-wwnn", &prop_val);
6213         if (rval == DDI_PROP_SUCCESS) {
6214                 rval = qlt_convert_string_to_ull(prop_val, radix, &wwnn);
6215         }
6216         if (rval == DDI_PROP_SUCCESS) {
6217                 rval = qlt_read_string_instance_prop(qlt, "adapter-wwpn",
6218                     &prop_val);
6219                 if (rval == DDI_PROP_SUCCESS) {
6220                         rval = qlt_convert_string_to_ull(prop_val, radix,
6221                             &wwpn);
6222                 }
6223         }
6224         if (rval == DDI_PROP_SUCCESS) {
6225                 overloaded = TRUE;
6226                 /* Overload the current node/port name nvram copy */
6227                 bcopy((char *)&wwnn, qlt->nvram->node_name, 8);
6228                 BIG_ENDIAN_64(qlt->nvram->node_name);
6229                 bcopy((char *)&wwpn, qlt->nvram->port_name, 8);
6230                 BIG_ENDIAN_64(qlt->nvram->port_name);
6231         }
6232         return (overloaded);
6233 }
6234 
6235 /*
6236  * prop_text - Return a pointer to a string describing the status
6237  *
6238  * Input:       prop_status = the return status from a property function.
6239  * Returns:     pointer to a string.
6240  * Context:     Kernel context.
6241  */
6242 char *
6243 prop_text(int prop_status)
6244 {
6245         string_table_t *entry = &prop_status_tbl[0];
6246 
6247         return (value2string(entry, prop_status, 0xFFFF));
6248 }
6249 
6250 /*
6251  * value2string Return a pointer to a string associated with the value
6252  *
6253  * Input:       entry = the value to string table
6254  *              value = the value
6255  * Returns:     pointer to a string.
6256  * Context:     Kernel context.
6257  */
6258 char *
6259 value2string(string_table_t *entry, int value, int delimiter)
6260 {
6261         for (; entry->value != delimiter; entry++) {
6262                 if (entry->value == value) {
6263                         break;
6264                 }
6265         }
6266         return (entry->string);
6267 }
6268 
6269 /*
6270  * qlt_chg_endian Change endianess of byte array.
6271  *
6272  * Input:       buf = array pointer.
6273  *              size = size of array in bytes.
6274  *
6275  * Context:     Interrupt or Kernel context.
6276  */
6277 void
6278 qlt_chg_endian(uint8_t buf[], size_t size)
6279 {
6280         uint8_t byte;
6281         size_t  cnt1;
6282         size_t  cnt;
6283 
6284         cnt1 = size - 1;
6285         for (cnt = 0; cnt < size / 2; cnt++) {
6286                 byte = buf[cnt1];
6287                 buf[cnt1] = buf[cnt];
6288                 buf[cnt] = byte;
6289                 cnt1--;
6290         }
6291 }
6292 
6293 /*
6294  * ql_mps_reset
6295  *      Reset MPS for FCoE functions.
6296  *
6297  * Input:
6298  *      ha = virtual adapter state pointer.
6299  *
6300  * Context:
6301  *      Kernel context.
6302  */
6303 static void
6304 qlt_mps_reset(qlt_state_t *qlt)
6305 {
6306         uint32_t        data, dctl = 1000;
6307 
6308         do {
6309                 if (dctl-- == 0 || qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 1) !=
6310                     QLT_SUCCESS) {
6311                         return;
6312                 }
6313                 if (qlt_raw_rd_risc_ram_word(qlt, 0x7c00, &data) !=
6314                     QLT_SUCCESS) {
6315                         (void) qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0);
6316                         return;
6317                 }
6318         } while (!(data & BIT_0));
6319 
6320         if (qlt_raw_rd_risc_ram_word(qlt, 0x7A15, &data) == QLT_SUCCESS) {
6321                 dctl = (uint16_t)PCICFG_RD16(qlt, 0x54);
6322                 if ((data & 0xe0) != (dctl & 0xe0)) {
6323                         data &= 0xff1f;
6324                         data |= dctl & 0xe0;
6325                         (void) qlt_raw_wrt_risc_ram_word(qlt, 0x7A15, data);
6326                 }
6327         }
6328         (void) qlt_raw_wrt_risc_ram_word(qlt, 0x7c00, 0);
6329 }
6330 
6331 /*
6332  * qlt_raw_wrt_risc_ram_word
6333  *      Write RISC RAM word.
6334  *
6335  * Input:       qlt:            adapter state pointer.
6336  *              risc_address:   risc ram word address.
6337  *              data:           data.
6338  *
6339  * Returns:     qlt local function return status code.
6340  *
6341  * Context:     Kernel context.
6342  */
6343 static fct_status_t
6344 qlt_raw_wrt_risc_ram_word(qlt_state_t *qlt, uint32_t risc_address,
6345     uint32_t data)
6346 {
6347         fct_status_t    ret;
6348 
6349         REG_WR16(qlt, REG_MBOX(0), MBC_WRITE_RAM_EXTENDED);
6350         REG_WR16(qlt, REG_MBOX(1), LSW(risc_address));
6351         REG_WR16(qlt, REG_MBOX(2), LSW(data));
6352         REG_WR16(qlt, REG_MBOX(3), MSW(data));
6353         REG_WR16(qlt, REG_MBOX(8), MSW(risc_address));
6354         ret = qlt_raw_mailbox_command(qlt);
6355         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
6356         if (ret != QLT_SUCCESS) {
6357                 EL(qlt, "qlt_raw_mailbox_command=MBC_WRITE_RAM_EXTENDED status"
6358                     "=%llxh\n", ret);
6359         }
6360         return (ret);
6361 }
6362 
6363 /*
6364  * ql_raw_rd_risc_ram_word
6365  *      Read RISC RAM word.
6366  *
6367  * Input:       qlt:            adapter state pointer.
6368  *              risc_address:   risc ram word address.
6369  *              data:           data pointer.
6370  *
6371  * Returns:     ql local function return status code.
6372  *
6373  * Context:     Kernel context.
6374  */
6375 static fct_status_t
6376 qlt_raw_rd_risc_ram_word(qlt_state_t *qlt, uint32_t risc_address,
6377     uint32_t *data)
6378 {
6379         fct_status_t    ret;
6380 
6381         REG_WR16(qlt, REG_MBOX(0), MBC_READ_RAM_EXTENDED);
6382         REG_WR16(qlt, REG_MBOX(1), LSW(risc_address));
6383         REG_WR16(qlt, REG_MBOX(2), MSW(risc_address));
6384         ret = qlt_raw_mailbox_command(qlt);
6385         *data = REG_RD16(qlt, REG_MBOX(2));
6386         *data |= (REG_RD16(qlt, REG_MBOX(3)) << 16);
6387         REG_WR32(qlt, REG_HCCR, HCCR_CMD(CLEAR_RISC_TO_PCI_INTR));
6388         if (ret != QLT_SUCCESS) {
6389                 EL(qlt, "qlt_raw_mailbox_command=MBC_READ_RAM_EXTENDED status"
6390                     "=%llxh\n", ret);
6391         }
6392         return (ret);
6393 }
6394 
6395 static void
6396 qlt_properties(qlt_state_t *qlt)
6397 {
6398         int32_t         cnt = 0;
6399         int32_t         defval = 0xffff;
6400 
6401         if (qlt_wwn_overload_prop(qlt) == TRUE) {
6402                 EL(qlt, "wwnn overloaded.\n");
6403         }
6404 
6405         if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt2k", defval)) !=
6406             defval) {
6407                 qlt->qlt_bucketcnt[0] = cnt;
6408                 EL(qlt, "2k bucket o/l=%d\n", cnt);
6409         }
6410 
6411         if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt8k", defval)) !=
6412             defval) {
6413                 qlt->qlt_bucketcnt[1] = cnt;
6414                 EL(qlt, "8k bucket o/l=%d\n", cnt);
6415         }
6416 
6417         if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt64k", defval)) !=
6418             defval) {
6419                 qlt->qlt_bucketcnt[2] = cnt;
6420                 EL(qlt, "64k bucket o/l=%d\n", cnt);
6421         }
6422 
6423         if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt128k", defval)) !=
6424             defval) {
6425                 qlt->qlt_bucketcnt[3] = cnt;
6426                 EL(qlt, "128k bucket o/l=%d\n", cnt);
6427         }
6428 
6429         if ((cnt = qlt_read_int_instance_prop(qlt, "bucketcnt256", defval)) !=
6430             defval) {
6431                 qlt->qlt_bucketcnt[4] = cnt;
6432                 EL(qlt, "256k bucket o/l=%d\n", cnt);
6433         }
6434 }
--- EOF ---