Print this page
NEX-5733 cleanup qlt/qlc
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5717 import QLogic 16G FC drivers
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-4957 Panic in qlc with QLE2460 in PCI passthrough mode on ESXi
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
        
*** 17,45 ****
   * information: Portions Copyright [yyyy] [name of copyright owner]
   *
   * CDDL HEADER END
   */
  
! /* Copyright 2010 QLogic Corporation */
  
  /*
!  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
   */
  /*
   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
   * Copyright (c) 2016 by Delphix. All rights reserved.
   */
  
! #pragma ident   "Copyright 2010 QLogic Corporation; ql_api.c"
  
  /*
   * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
   *
   * ***********************************************************************
   * *                                                                    **
   * *                            NOTICE                                  **
!  * *            COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION              **
   * *                    ALL RIGHTS RESERVED                             **
   * *                                                                    **
   * ***********************************************************************
   *
   */
--- 17,45 ----
   * information: Portions Copyright [yyyy] [name of copyright owner]
   *
   * CDDL HEADER END
   */
  
! /* Copyright 2015 QLogic Corporation */
  
  /*
!  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
   */
  /*
   * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
   * Copyright (c) 2016 by Delphix. All rights reserved.
   */
  
! #pragma ident   "Copyright 2015 QLogic Corporation; ql_api.c"
  
  /*
   * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file.
   *
   * ***********************************************************************
   * *                                                                    **
   * *                            NOTICE                                  **
!  * *            COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION              **
   * *                    ALL RIGHTS RESERVED                             **
   * *                                                                    **
   * ***********************************************************************
   *
   */
*** 52,61 ****
--- 52,62 ----
  #include <ql_ioctl.h>
  #include <ql_isr.h>
  #include <ql_mbx.h>
  #include <ql_nx.h>
  #include <ql_xioctl.h>
+ #include <ql_fm.h>
  
  /*
   * Solaris external defines.
   */
  extern pri_t minclsyspri;
*** 92,115 ****
  static opaque_t ql_get_device(opaque_t, fc_portid_t);
  
  /*
   * FCA Driver Support Function Prototypes.
   */
! static uint16_t ql_wait_outstanding(ql_adapter_state_t *);
! static void ql_task_mgmt(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
!     ql_srb_t *);
! static void ql_task_daemon(void *);
! static void ql_task_thread(ql_adapter_state_t *);
! static void ql_unsol_callback(ql_srb_t *);
! static void ql_free_unsolicited_buffer(ql_adapter_state_t *,
!     fc_unsol_buf_t *);
! static void ql_timer(void *);
! static void ql_watchdog(ql_adapter_state_t *, uint32_t *, uint32_t *);
! static void ql_cmd_timeout(ql_adapter_state_t *, ql_tgt_t *q, ql_srb_t *,
!     uint32_t *, uint32_t *);
! static void ql_halt(ql_adapter_state_t *, int);
  static int ql_els_plogi(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_flogi(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_logo(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_prli(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_prlo(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_adisc(ql_adapter_state_t *, fc_packet_t *);
--- 93,105 ----
  static opaque_t ql_get_device(opaque_t, fc_portid_t);
  
  /*
   * FCA Driver Support Function Prototypes.
   */
! static ql_adapter_state_t *ql_cmd_setup(opaque_t, fc_packet_t *, int *);
  static int ql_els_plogi(ql_adapter_state_t *, fc_packet_t *);
+ static int ql_p2p_plogi(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_flogi(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_logo(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_prli(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_prlo(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_adisc(ql_adapter_state_t *, fc_packet_t *);
*** 118,207 ****
  static int ql_els_lsts(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_scr(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_rscn(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_farp_req(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_farp_reply(ql_adapter_state_t *, fc_packet_t *);
- static int ql_els_rls(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_rnid(ql_adapter_state_t *, fc_packet_t *);
  static int ql_login_port(ql_adapter_state_t *, port_id_t);
  static int ql_login_fabric_port(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
  static int ql_logout_port(ql_adapter_state_t *, port_id_t);
! static ql_lun_t *ql_lun_queue(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
  static int ql_fcp_scsi_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
  static int ql_fcp_ip_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
  static int ql_fc_services(ql_adapter_state_t *, fc_packet_t *);
- static int ql_poll_cmd(ql_adapter_state_t *, ql_srb_t *, time_t);
  static int ql_start_cmd(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
      ql_srb_t *);
! static int ql_kstat_update(kstat_t *, int);
! static ql_adapter_state_t *ql_fca_handle_to_state(opaque_t);
! static ql_adapter_state_t *ql_cmd_setup(opaque_t, fc_packet_t *, int *);
! static int ql_program_flash_address(ql_adapter_state_t *, uint32_t, uint8_t);
! static void ql_rst_aen(ql_adapter_state_t *);
! static void ql_restart_queues(ql_adapter_state_t *);
! static void ql_abort_queues(ql_adapter_state_t *);
! static void ql_abort_device_queues(ql_adapter_state_t *ha, ql_tgt_t *tq);
  static void ql_idle_check(ql_adapter_state_t *);
! static int ql_loop_resync(ql_adapter_state_t *);
! static size_t ql_24xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
! static size_t ql_2581_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
! static int ql_save_config_regs(dev_info_t *);
! static int ql_restore_config_regs(dev_info_t *);
! static int ql_process_rscn(ql_adapter_state_t *, fc_affected_id_t *);
! static int ql_handle_rscn_update(ql_adapter_state_t *);
  static int ql_send_plogi(ql_adapter_state_t *, ql_tgt_t *, ql_head_t *);
  static int ql_process_rscn_for_device(ql_adapter_state_t *, ql_tgt_t *);
! static int ql_dump_firmware(ql_adapter_state_t *);
! static int ql_process_logo_for_device(ql_adapter_state_t *, ql_tgt_t *);
  static int ql_2200_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
  static int ql_2300_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
  static int ql_24xx_binary_fw_dump(ql_adapter_state_t *, ql_24xx_fw_dump_t *);
  static int ql_25xx_binary_fw_dump(ql_adapter_state_t *, ql_25xx_fw_dump_t *);
  static int ql_81xx_binary_fw_dump(ql_adapter_state_t *, ql_81xx_fw_dump_t *);
  static int ql_read_risc_ram(ql_adapter_state_t *, uint32_t, uint32_t,
      void *);
  static void *ql_read_regs(ql_adapter_state_t *, void *, void *, uint32_t,
      uint8_t);
! static int ql_busy_plogi(ql_adapter_state_t *, fc_packet_t *, ql_tgt_t *);
! static int ql_suspend_adapter(ql_adapter_state_t *);
! static int ql_bstr_to_dec(char *, uint32_t *, uint32_t);
! static void ql_update_rscn(ql_adapter_state_t *, fc_affected_id_t *);
! int ql_alloc_dma_resouce(ql_adapter_state_t *, dma_mem_t *, int);
  static int ql_bind_dma_buffer(ql_adapter_state_t *, dma_mem_t *, int);
  static void ql_unbind_dma_buffer(ql_adapter_state_t *, dma_mem_t *);
! static void ql_timeout_insert(ql_adapter_state_t *, ql_tgt_t *, ql_srb_t *);
  static int ql_setup_interrupts(ql_adapter_state_t *);
  static int ql_setup_msi(ql_adapter_state_t *);
  static int ql_setup_msix(ql_adapter_state_t *);
  static int ql_setup_fixed(ql_adapter_state_t *);
  static void ql_release_intr(ql_adapter_state_t *);
- static void ql_disable_intr(ql_adapter_state_t *);
  static int ql_legacy_intr(ql_adapter_state_t *);
  static int ql_init_mutex(ql_adapter_state_t *);
  static void ql_destroy_mutex(ql_adapter_state_t *);
! static void ql_iidma(ql_adapter_state_t *);
! 
! static int ql_n_port_plogi(ql_adapter_state_t *);
! static void ql_fca_isp_els_request(ql_adapter_state_t *, fc_packet_t *,
!     els_descriptor_t *);
  static void ql_isp_els_request_ctor(els_descriptor_t *,
      els_passthru_entry_t *);
! static int ql_p2p_plogi(ql_adapter_state_t *, fc_packet_t *);
! static int ql_wait_for_td_stop(ql_adapter_state_t *);
! static void ql_process_idc_event(ql_adapter_state_t *);
  
  /*
   * Global data
   */
  static uint8_t  ql_enable_pm = 1;
  static int      ql_flash_sbus_fpga = 0;
  uint32_t        ql_os_release_level;
  uint32_t        ql_disable_aif = 0;
  uint32_t        ql_disable_msi = 0;
  uint32_t        ql_disable_msix = 0;
  uint32_t        ql_enable_ets = 0;
  uint16_t        ql_osc_wait_count = 1000;
  
  /* Timer routine variables. */
  static timeout_id_t     ql_timer_timeout_id = NULL;
  static clock_t          ql_timer_ticks;
  
--- 108,263 ----
  static int ql_els_lsts(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_scr(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_rscn(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_farp_req(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_farp_reply(ql_adapter_state_t *, fc_packet_t *);
  static int ql_els_rnid(ql_adapter_state_t *, fc_packet_t *);
+ static int ql_els_rls(ql_adapter_state_t *, fc_packet_t *);
+ static int ql_busy_plogi(ql_adapter_state_t *, fc_packet_t *, ql_tgt_t *);
  static int ql_login_port(ql_adapter_state_t *, port_id_t);
  static int ql_login_fabric_port(ql_adapter_state_t *, ql_tgt_t *, uint16_t);
  static int ql_logout_port(ql_adapter_state_t *, port_id_t);
! static ql_lun_t *ql_lun_queue(ql_adapter_state_t *, ql_tgt_t *, uint64_t);
  static int ql_fcp_scsi_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
+ static void ql_task_mgmt(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
+     ql_srb_t *);
  static int ql_fcp_ip_cmd(ql_adapter_state_t *, fc_packet_t *, ql_srb_t *);
  static int ql_fc_services(ql_adapter_state_t *, fc_packet_t *);
  static int ql_start_cmd(ql_adapter_state_t *, ql_tgt_t *, fc_packet_t *,
      ql_srb_t *);
! static int ql_poll_cmd(ql_adapter_state_t *, ql_srb_t *, time_t);
! static void ql_task_daemon(void *);
! static void ql_task_thread(ql_adapter_state_t *);
  static void ql_idle_check(ql_adapter_state_t *);
! static void ql_unsol_callback(ql_srb_t *);
! static int ql_process_logo_for_device(ql_adapter_state_t *, ql_tgt_t *);
  static int ql_send_plogi(ql_adapter_state_t *, ql_tgt_t *, ql_head_t *);
+ static void ql_update_rscn(ql_adapter_state_t *, fc_affected_id_t *);
+ static int ql_process_rscn(ql_adapter_state_t *, fc_affected_id_t *);
  static int ql_process_rscn_for_device(ql_adapter_state_t *, ql_tgt_t *);
! static int ql_handle_rscn_update(ql_adapter_state_t *);
! static void ql_free_unsolicited_buffer(ql_adapter_state_t *,
!     fc_unsol_buf_t *);
! static void ql_timer(void *);
! static void ql_timeout_insert(ql_adapter_state_t *, ql_tgt_t *, ql_srb_t *);
! static void ql_watchdog(ql_adapter_state_t *);
! static void ql_wdg_tq_list(ql_adapter_state_t *, ql_tgt_t *);
! static void ql_cmd_timeout(ql_adapter_state_t *, ql_tgt_t *q, ql_srb_t *);
! static uint16_t ql_wait_outstanding(ql_adapter_state_t *);
! static void ql_iidma(ql_adapter_state_t *);
! static void ql_abort_device_queues(ql_adapter_state_t *ha, ql_tgt_t *tq);
! static void ql_loop_resync(ql_adapter_state_t *);
! static ql_adapter_state_t *ql_fca_handle_to_state(opaque_t);
! static int ql_kstat_update(kstat_t *, int);
! static int ql_program_flash_address(ql_adapter_state_t *, uint32_t, uint8_t);
! static size_t ql_24xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
! static size_t ql_25xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
! static size_t ql_81xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
! static size_t ql_8021_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
  static int ql_2200_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
  static int ql_2300_binary_fw_dump(ql_adapter_state_t *, ql_fw_dump_t *);
  static int ql_24xx_binary_fw_dump(ql_adapter_state_t *, ql_24xx_fw_dump_t *);
  static int ql_25xx_binary_fw_dump(ql_adapter_state_t *, ql_25xx_fw_dump_t *);
  static int ql_81xx_binary_fw_dump(ql_adapter_state_t *, ql_81xx_fw_dump_t *);
  static int ql_read_risc_ram(ql_adapter_state_t *, uint32_t, uint32_t,
      void *);
  static void *ql_read_regs(ql_adapter_state_t *, void *, void *, uint32_t,
      uint8_t);
! static int ql_save_config_regs(dev_info_t *);
! static int ql_restore_config_regs(dev_info_t *);
! static void ql_halt(ql_adapter_state_t *, int);
  static int ql_bind_dma_buffer(ql_adapter_state_t *, dma_mem_t *, int);
  static void ql_unbind_dma_buffer(ql_adapter_state_t *, dma_mem_t *);
! static int ql_suspend_adapter(ql_adapter_state_t *);
! static int ql_bstr_to_dec(char *, uint32_t *, uint32_t);
  static int ql_setup_interrupts(ql_adapter_state_t *);
  static int ql_setup_msi(ql_adapter_state_t *);
  static int ql_setup_msix(ql_adapter_state_t *);
  static int ql_setup_fixed(ql_adapter_state_t *);
  static void ql_release_intr(ql_adapter_state_t *);
  static int ql_legacy_intr(ql_adapter_state_t *);
  static int ql_init_mutex(ql_adapter_state_t *);
  static void ql_destroy_mutex(ql_adapter_state_t *);
! static void ql_fca_isp_els_request(ql_adapter_state_t *, ql_request_q_t *,
!     fc_packet_t *, els_descriptor_t *);
  static void ql_isp_els_request_ctor(els_descriptor_t *,
      els_passthru_entry_t *);
! static int ql_n_port_plogi(ql_adapter_state_t *);
! static int ql_create_queues(ql_adapter_state_t *);
! static int ql_create_rsp_queue(ql_adapter_state_t *, uint16_t);
! static void ql_delete_queues(ql_adapter_state_t *);
! static int ql_multi_queue_support(ql_adapter_state_t *);
! static int ql_map_mem_bar(ql_adapter_state_t *, ddi_acc_handle_t *, caddr_t *,
!     uint32_t, uint32_t);
! static void ql_completion_thread(void *);
! static void ql_process_comp_queue(void *);
! static int ql_abort_io(ql_adapter_state_t *vha, ql_srb_t *);
! static void ql_idc(ql_adapter_state_t *);
! static int ql_83xx_binary_fw_dump(ql_adapter_state_t *, ql_83xx_fw_dump_t *);
! static size_t ql_83xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
! static caddr_t ql_str_ptr(ql_adapter_state_t *, caddr_t, uint32_t *);
! static int ql_27xx_binary_fw_dump(ql_adapter_state_t *);
! static size_t ql_27xx_ascii_fw_dump(ql_adapter_state_t *, caddr_t);
! static uint32_t ql_2700_dmp_parse_template(ql_adapter_state_t *, ql_dt_hdr_t *,
!     uint8_t *, uint32_t);
! static int ql_2700_dt_riob1(ql_adapter_state_t *, ql_dt_riob1_t *, uint8_t *,
!     uint8_t *);
! static void ql_2700_dt_wiob1(ql_adapter_state_t *, ql_dt_wiob1_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_riob2(ql_adapter_state_t *, ql_dt_riob2_t *, uint8_t *,
!     uint8_t *);
! static void ql_2700_dt_wiob2(ql_adapter_state_t *, ql_dt_wiob2_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_rpci(ql_adapter_state_t *, ql_dt_rpci_t *, uint8_t *,
!     uint8_t *);
! static void ql_2700_dt_wpci(ql_adapter_state_t *, ql_dt_wpci_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_rram(ql_adapter_state_t *, ql_dt_rram_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_gque(ql_adapter_state_t *, ql_dt_gque_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_gfce(ql_adapter_state_t *, ql_dt_gfce_t *, uint8_t *,
!     uint8_t *);
! static void ql_2700_dt_prisc(ql_adapter_state_t *, ql_dt_prisc_t *, uint8_t *,
!     uint8_t *);
! static void ql_2700_dt_rrisc(ql_adapter_state_t *, ql_dt_rrisc_t *, uint8_t *,
!     uint8_t *);
! static void ql_2700_dt_dint(ql_adapter_state_t *, ql_dt_dint_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_ghbd(ql_adapter_state_t *, ql_dt_ghbd_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_scra(ql_adapter_state_t *, ql_dt_scra_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_rrreg(ql_adapter_state_t *, ql_dt_rrreg_t *, uint8_t *,
!     uint8_t *);
! static void ql_2700_dt_wrreg(ql_adapter_state_t *, ql_dt_wrreg_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_rrram(ql_adapter_state_t *, ql_dt_rrram_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_rpcic(ql_adapter_state_t *, ql_dt_rpcic_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_gques(ql_adapter_state_t *, ql_dt_gques_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dt_wdmp(ql_adapter_state_t *, ql_dt_wdmp_t *, uint8_t *,
!     uint8_t *);
! static int ql_2700_dump_ram(ql_adapter_state_t *, uint16_t, uint32_t, uint32_t,
!     uint8_t *);
  
  /*
   * Global data
   */
  static uint8_t  ql_enable_pm = 1;
  static int      ql_flash_sbus_fpga = 0;
  uint32_t        ql_os_release_level;
  uint32_t        ql_disable_aif = 0;
+ uint32_t        ql_disable_intx = 0;
  uint32_t        ql_disable_msi = 0;
  uint32_t        ql_disable_msix = 0;
  uint32_t        ql_enable_ets = 0;
  uint16_t        ql_osc_wait_count = 1000;
+ uint32_t        ql_task_cb_dly = 64;
+ uint32_t        qlc_disable_load = 0;
  
  /* Timer routine variables. */
  static timeout_id_t     ql_timer_timeout_id = NULL;
  static clock_t          ql_timer_ticks;
  
*** 452,475 ****
          0x54,   /* io_base_addr */
          0x380,  /* nx_host_int */
          0x504   /* nx_risc_int */
  };
  
  /* mutex for protecting variables shared by all instances of the driver */
  kmutex_t ql_global_mutex;
  kmutex_t ql_global_hw_mutex;
  kmutex_t ql_global_el_mutex;
  
  /* DMA access attribute structure. */
! static ddi_device_acc_attr_t ql_dev_acc_attr = {
          DDI_DEVICE_ATTR_V0,
          DDI_STRUCTURE_LE_ACC,
          DDI_STRICTORDER_ACC
  };
  
  /* I/O DMA attributes structures. */
! static ddi_dma_attr_t ql_64bit_io_dma_attr = {
          DMA_ATTR_V0,                    /* dma_attr_version */
          QL_DMA_LOW_ADDRESS,             /* low DMA address range */
          QL_DMA_HIGH_64BIT_ADDRESS,      /* high DMA address range */
          QL_DMA_XFER_COUNTER,            /* DMA counter register */
          QL_DMA_ADDRESS_ALIGNMENT,       /* DMA address alignment */
--- 508,577 ----
          0x54,   /* io_base_addr */
          0x380,  /* nx_host_int */
          0x504   /* nx_risc_int */
  };
  
+ /* 2700/8300 register offsets */
+ static reg_off_t reg_off_2700_8300 = {
+         0x00,   /* flash_address */
+         0x04,   /* flash_data */
+         0x08,   /* ctrl_status */
+         0x0c,   /* ictrl */
+         0x10,   /* istatus */
+         0xff,   /* semaphore - n/a */
+         0xff,   /* nvram - n/a */
+         0xff,   /* req_in - n/a */
+         0xff,   /* req_out - n/a */
+         0xff,   /* resp_in - n/a */
+         0xff,   /* resp_out - n/a */
+         0x44,   /* risc2host */
+         32,     /* Number of mailboxes */
+ 
+         /* Mailbox in register offsets 0 - 31 */
+         0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
+         0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
+         0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
+         0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
+ 
+         /* Mailbox out register offsets 0 - 31 */
+         0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e,
+         0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
+         0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae,
+         0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
+ 
+         0xff,   /* fpm_diag_config - n/a */
+         0xff,   /* pcr - n/a */
+         0xff,   /* mctr - n/a */
+         0xff,   /* fb_cmd - n/a */
+         0x48,   /* hccr */
+         0x4c,   /* gpiod */
+         0x50,   /* gpioe */
+         0x58,   /* host_to_host_sema - n/a */
+         0xff,   /* pri_req_in - n/a */
+         0xff,   /* pri_req_out - n/a */
+         0xff,   /* atio_req_in - n/a */
+         0xff,   /* atio_req_out - n/a */
+         0x54,   /* io_base_addr */
+         0xff,   /* nx_host_int - n/a */
+         0xff    /* nx_risc_int - n/a */
+ };
+ 
  /* mutex for protecting variables shared by all instances of the driver */
  kmutex_t ql_global_mutex;
  kmutex_t ql_global_hw_mutex;
  kmutex_t ql_global_el_mutex;
+ kmutex_t ql_global_timer_mutex;
  
  /* DMA access attribute structure. */
! ddi_device_acc_attr_t ql_dev_acc_attr = {
          DDI_DEVICE_ATTR_V0,
          DDI_STRUCTURE_LE_ACC,
          DDI_STRICTORDER_ACC
  };
  
  /* I/O DMA attributes structures. */
! ddi_dma_attr_t ql_64bit_io_dma_attr = {
          DMA_ATTR_V0,                    /* dma_attr_version */
          QL_DMA_LOW_ADDRESS,             /* low DMA address range */
          QL_DMA_HIGH_64BIT_ADDRESS,      /* high DMA address range */
          QL_DMA_XFER_COUNTER,            /* DMA counter register */
          QL_DMA_ADDRESS_ALIGNMENT,       /* DMA address alignment */
*** 480,490 ****
          QL_DMA_SG_LIST_LENGTH,          /* s/g list length */
          QL_DMA_GRANULARITY,             /* granularity of device */
          QL_DMA_XFER_FLAGS               /* DMA transfer flags */
  };
  
! static ddi_dma_attr_t ql_32bit_io_dma_attr = {
          DMA_ATTR_V0,                    /* dma_attr_version */
          QL_DMA_LOW_ADDRESS,             /* low DMA address range */
          QL_DMA_HIGH_32BIT_ADDRESS,      /* high DMA address range */
          QL_DMA_XFER_COUNTER,            /* DMA counter register */
          QL_DMA_ADDRESS_ALIGNMENT,       /* DMA address alignment */
--- 582,592 ----
          QL_DMA_SG_LIST_LENGTH,          /* s/g list length */
          QL_DMA_GRANULARITY,             /* granularity of device */
          QL_DMA_XFER_FLAGS               /* DMA transfer flags */
  };
  
! ddi_dma_attr_t ql_32bit_io_dma_attr = {
          DMA_ATTR_V0,                    /* dma_attr_version */
          QL_DMA_LOW_ADDRESS,             /* low DMA address range */
          QL_DMA_HIGH_32BIT_ADDRESS,      /* high DMA address range */
          QL_DMA_XFER_COUNTER,            /* DMA counter register */
          QL_DMA_ADDRESS_ALIGNMENT,       /* DMA address alignment */
*** 495,520 ****
          QL_DMA_SG_LIST_LENGTH,          /* s/g list length */
          QL_DMA_GRANULARITY,             /* granularity of device */
          QL_DMA_XFER_FLAGS               /* DMA transfer flags */
  };
  
- /* Load the default dma attributes */
- static  ddi_dma_attr_t  ql_32fcsm_cmd_dma_attr;
- static  ddi_dma_attr_t  ql_64fcsm_cmd_dma_attr;
- static  ddi_dma_attr_t  ql_32fcsm_rsp_dma_attr;
- static  ddi_dma_attr_t  ql_64fcsm_rsp_dma_attr;
- static  ddi_dma_attr_t  ql_32fcip_cmd_dma_attr;
- static  ddi_dma_attr_t  ql_64fcip_cmd_dma_attr;
- static  ddi_dma_attr_t  ql_32fcip_rsp_dma_attr;
- static  ddi_dma_attr_t  ql_64fcip_rsp_dma_attr;
- static  ddi_dma_attr_t  ql_32fcp_cmd_dma_attr;
- static  ddi_dma_attr_t  ql_64fcp_cmd_dma_attr;
- static  ddi_dma_attr_t  ql_32fcp_rsp_dma_attr;
- static  ddi_dma_attr_t  ql_64fcp_rsp_dma_attr;
- static  ddi_dma_attr_t  ql_32fcp_data_dma_attr;
- static  ddi_dma_attr_t  ql_64fcp_data_dma_attr;
- 
  /* Static declarations of cb_ops entry point functions... */
  static struct cb_ops ql_cb_ops = {
          ql_open,                        /* b/c open */
          ql_close,                       /* b/c close */
          nodev,                          /* b strategy */
--- 597,606 ----
*** 554,565 ****
  /* ELS command code to text converter */
  cmd_table_t els_cmd_tbl[] = ELS_CMD_TABLE();
  /* Mailbox command code to text converter */
  cmd_table_t mbox_cmd_tbl[] = MBOX_CMD_TABLE();
  
! char qlc_driver_version[] = QL_VERSION;
  
  /*
   * Loadable Driver Interface Structures.
   * Declare and initialize the module configuration section...
   */
  static struct modldrv modldrv = {
--- 640,653 ----
  /* ELS command code to text converter */
  cmd_table_t els_cmd_tbl[] = ELS_CMD_TABLE();
  /* Mailbox command code to text converter */
  cmd_table_t mbox_cmd_tbl[] = MBOX_CMD_TABLE();
  
! char ql_driver_version[] = QL_VERSION;
  
+ uint32_t ql_log_entries = QL_LOG_ENTRIES;
+ 
  /*
   * Loadable Driver Interface Structures.
   * Declare and initialize the module configuration section...
   */
  static struct modldrv modldrv = {
*** 593,602 ****
--- 681,695 ----
  _init(void)
  {
          uint16_t        w16;
          int             rval = 0;
  
+         if (qlc_disable_load) {
+                 cmn_err(CE_WARN, "%s load disabled", QL_NAME);
+                 return (EINVAL);
+         }
+ 
          /* Get OS major release level. */
          for (w16 = 0; w16 < sizeof (utsname.release); w16++) {
                  if (utsname.release[w16] == '.') {
                          w16++;
                          break;
*** 627,676 ****
                  fc_fca_init(&ql_devops);
  
                  mutex_init(&ql_global_mutex, NULL, MUTEX_DRIVER, NULL);
                  mutex_init(&ql_global_hw_mutex, NULL, MUTEX_DRIVER, NULL);
                  mutex_init(&ql_global_el_mutex, NULL, MUTEX_DRIVER, NULL);
                  rval = mod_install(&modlinkage);
                  if (rval != 0) {
                          mutex_destroy(&ql_global_hw_mutex);
                          mutex_destroy(&ql_global_mutex);
-                         mutex_destroy(&ql_global_el_mutex);
                          ddi_soft_state_fini(&ql_state);
-                 } else {
-                         /*EMPTY*/
-                         ql_32fcsm_cmd_dma_attr = ql_32bit_io_dma_attr;
-                         ql_64fcsm_cmd_dma_attr = ql_64bit_io_dma_attr;
-                         ql_32fcsm_rsp_dma_attr = ql_32bit_io_dma_attr;
-                         ql_64fcsm_rsp_dma_attr = ql_64bit_io_dma_attr;
-                         ql_32fcip_cmd_dma_attr = ql_32bit_io_dma_attr;
-                         ql_64fcip_cmd_dma_attr = ql_64bit_io_dma_attr;
-                         ql_32fcip_rsp_dma_attr = ql_32bit_io_dma_attr;
-                         ql_64fcip_rsp_dma_attr = ql_64bit_io_dma_attr;
-                         ql_32fcp_cmd_dma_attr = ql_32bit_io_dma_attr;
-                         ql_64fcp_cmd_dma_attr = ql_64bit_io_dma_attr;
-                         ql_32fcp_rsp_dma_attr = ql_32bit_io_dma_attr;
-                         ql_64fcp_rsp_dma_attr = ql_64bit_io_dma_attr;
-                         ql_32fcp_data_dma_attr = ql_32bit_io_dma_attr;
-                         ql_64fcp_data_dma_attr = ql_64bit_io_dma_attr;
-                         ql_32fcsm_cmd_dma_attr.dma_attr_sgllen =
-                             ql_64fcsm_cmd_dma_attr.dma_attr_sgllen =
-                             QL_FCSM_CMD_SGLLEN;
-                         ql_32fcsm_rsp_dma_attr.dma_attr_sgllen =
-                             ql_64fcsm_rsp_dma_attr.dma_attr_sgllen =
-                             QL_FCSM_RSP_SGLLEN;
-                         ql_32fcip_cmd_dma_attr.dma_attr_sgllen =
-                             ql_64fcip_cmd_dma_attr.dma_attr_sgllen =
-                             QL_FCIP_CMD_SGLLEN;
-                         ql_32fcip_rsp_dma_attr.dma_attr_sgllen =
-                             ql_64fcip_rsp_dma_attr.dma_attr_sgllen =
-                             QL_FCIP_RSP_SGLLEN;
-                         ql_32fcp_cmd_dma_attr.dma_attr_sgllen =
-                             ql_64fcp_cmd_dma_attr.dma_attr_sgllen =
-                             QL_FCP_CMD_SGLLEN;
-                         ql_32fcp_rsp_dma_attr.dma_attr_sgllen =
-                             ql_64fcp_rsp_dma_attr.dma_attr_sgllen =
-                             QL_FCP_RSP_SGLLEN;
                  }
          }
  
          if (rval != 0) {
                  cmn_err(CE_CONT, "?Unable to install/attach driver '%s'",
--- 720,737 ----
                  fc_fca_init(&ql_devops);
  
                  mutex_init(&ql_global_mutex, NULL, MUTEX_DRIVER, NULL);
                  mutex_init(&ql_global_hw_mutex, NULL, MUTEX_DRIVER, NULL);
                  mutex_init(&ql_global_el_mutex, NULL, MUTEX_DRIVER, NULL);
+                 mutex_init(&ql_global_timer_mutex, NULL, MUTEX_DRIVER, NULL);
                  rval = mod_install(&modlinkage);
                  if (rval != 0) {
+                         mutex_destroy(&ql_global_timer_mutex);
+                         mutex_destroy(&ql_global_el_mutex);
                          mutex_destroy(&ql_global_hw_mutex);
                          mutex_destroy(&ql_global_mutex);
                          ddi_soft_state_fini(&ql_state);
                  }
          }
  
          if (rval != 0) {
                  cmn_err(CE_CONT, "?Unable to install/attach driver '%s'",
*** 699,711 ****
  {
          int     rval;
  
          rval = mod_remove(&modlinkage);
          if (rval == 0) {
                  mutex_destroy(&ql_global_hw_mutex);
                  mutex_destroy(&ql_global_mutex);
-                 mutex_destroy(&ql_global_el_mutex);
                  ddi_soft_state_fini(&ql_state);
          }
  
          return (rval);
  }
--- 760,773 ----
  {
          int     rval;
  
          rval = mod_remove(&modlinkage);
          if (rval == 0) {
+                 mutex_destroy(&ql_global_timer_mutex);
+                 mutex_destroy(&ql_global_el_mutex);
                  mutex_destroy(&ql_global_hw_mutex);
                  mutex_destroy(&ql_global_mutex);
                  ddi_soft_state_fini(&ql_state);
          }
  
          return (rval);
  }
*** 761,777 ****
          int                     rval = DDI_FAILURE;
  
          minor = (int)(getminor((dev_t)arg));
          ha = ddi_get_soft_state(ql_state, minor);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, unknown minor=%d\n",
                      getminor((dev_t)arg));
                  *resultp = NULL;
                  return (rval);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          switch (cmd) {
          case DDI_INFO_DEVT2DEVINFO:
                  *resultp = ha->dip;
                  rval = DDI_SUCCESS;
--- 823,839 ----
          int                     rval = DDI_FAILURE;
  
          minor = (int)(getminor((dev_t)arg));
          ha = ddi_get_soft_state(ql_state, minor);
          if (ha == NULL) {
!                 QL_PRINT_2(ha, "failed, unknown minor=%d\n",
                      getminor((dev_t)arg));
                  *resultp = NULL;
                  return (rval);
          }
  
!         QL_PRINT_3(ha, "started\n");
  
          switch (cmd) {
          case DDI_INFO_DEVT2DEVINFO:
                  *resultp = ha->dip;
                  rval = DDI_SUCCESS;
*** 784,794 ****
                  EL(ha, "failed, unsupported cmd=%d\n", cmd);
                  rval = DDI_FAILURE;
                  break;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 846,856 ----
                  EL(ha, "failed, unsupported cmd=%d\n", cmd);
                  rval = DDI_FAILURE;
                  break;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 810,842 ****
  ql_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
  {
          off_t                   regsize;
          uint32_t                size;
          int                     rval, *ptr;
-         int                     instance;
          uint_t                  progress = 0;
!         char                    *buf;
          ushort_t                caps_ptr, cap;
          fc_fca_tran_t           *tran;
          ql_adapter_state_t      *ha = NULL;
  
          static char *pmcomps[] = {
                  NULL,
                  PM_LEVEL_D3_STR,                /* Device OFF */
                  PM_LEVEL_D0_STR,                /* Device ON */
          };
  
!         QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n",
              ddi_get_instance(dip), cmd);
  
          buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
  
          switch (cmd) {
          case DDI_ATTACH:
-                 /* first get the instance */
-                 instance = ddi_get_instance(dip);
- 
                  cmn_err(CE_CONT, "!Qlogic %s(%d) FCA Driver v%s\n",
                      QL_NAME, instance, QL_VERSION);
  
                  /* Correct OS version? */
                  if (ql_os_release_level != 11) {
--- 872,901 ----
  ql_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
  {
          off_t                   regsize;
          uint32_t                size;
          int                     rval, *ptr;
          uint_t                  progress = 0;
!         char                    *buf, taskq_name[32];
          ushort_t                caps_ptr, cap;
          fc_fca_tran_t           *tran;
          ql_adapter_state_t      *ha = NULL;
+         int                     instance = ddi_get_instance(dip);
  
          static char *pmcomps[] = {
                  NULL,
                  PM_LEVEL_D3_STR,                /* Device OFF */
                  PM_LEVEL_D0_STR,                /* Device ON */
          };
  
!         QL_PRINT_3(NULL, "started, instance=%d, cmd=%xh\n",
              ddi_get_instance(dip), cmd);
  
          buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
  
          switch (cmd) {
          case DDI_ATTACH:
                  cmn_err(CE_CONT, "!Qlogic %s(%d) FCA Driver v%s\n",
                      QL_NAME, instance, QL_VERSION);
  
                  /* Correct OS version? */
                  if (ql_os_release_level != 11) {
*** 850,874 ****
                          cmn_err(CE_WARN, "%s(%d): slave only", QL_NAME,
                              instance);
                          goto attach_failed;
                  }
  
-                 /* No support for high-level interrupts */
-                 if (ddi_intr_hilevel(dip, 0) != 0) {
-                         cmn_err(CE_WARN, "%s(%d): High level interrupt"
-                             " not supported", QL_NAME, instance);
-                         goto attach_failed;
-                 }
- 
                  /* Allocate our per-device-instance structure */
                  if (ddi_soft_state_zalloc(ql_state,
                      instance) != DDI_SUCCESS) {
                          cmn_err(CE_WARN, "%s(%d): soft state alloc failed",
                              QL_NAME, instance);
                          goto attach_failed;
                  }
-                 progress |= QL_SOFT_STATE_ALLOCED;
  
                  ha = ddi_get_soft_state(ql_state, instance);
                  if (ha == NULL) {
                          cmn_err(CE_WARN, "%s(%d): can't get soft state",
                              QL_NAME, instance);
--- 909,925 ----
*** 877,916 ****
                  ha->dip = dip;
                  ha->instance = instance;
                  ha->hba.base_address = ha;
                  ha->pha = ha;
  
!                 if (ql_el_trace_desc_ctor(ha) != DDI_SUCCESS) {
!                         cmn_err(CE_WARN, "%s(%d): can't setup el tracing",
!                             QL_NAME, instance);
!                         goto attach_failed;
!                 }
  
                  /* Get extended logging and dump flags. */
                  ql_common_properties(ha);
  
                  if (strcmp(ddi_driver_name(ddi_get_parent(dip)),
                      "sbus") == 0) {
!                         EL(ha, "%s SBUS card detected", QL_NAME);
                          ha->cfg_flags |= CFG_SBUS_CARD;
                  }
  
                  ha->dev = kmem_zalloc(sizeof (*ha->dev) *
                      DEVICE_HEAD_LIST_SIZE, KM_SLEEP);
  
-                 ha->outstanding_cmds = kmem_zalloc(
-                     sizeof (*ha->outstanding_cmds) * MAX_OUTSTANDING_COMMANDS,
-                     KM_SLEEP);
- 
                  ha->ub_array = kmem_zalloc(sizeof (*ha->ub_array) *
                      QL_UB_LIMIT, KM_SLEEP);
  
                  ha->adapter_stats = kmem_zalloc(sizeof (*ha->adapter_stats),
                      KM_SLEEP);
  
                  (void) ddi_pathname(dip, buf);
!                 ha->devpath = kmem_zalloc(strlen(buf)+1, KM_SLEEP);
                  if (ha->devpath == NULL) {
                          EL(ha, "devpath mem alloc failed\n");
                  } else {
                          (void) strcpy(ha->devpath, buf);
                          EL(ha, "devpath is: %s\n", ha->devpath);
--- 928,969 ----
                  ha->dip = dip;
                  ha->instance = instance;
                  ha->hba.base_address = ha;
                  ha->pha = ha;
  
!                 ha->bit32_io_dma_attr = ql_32bit_io_dma_attr;
!                 ha->bit64_io_dma_attr = ql_64bit_io_dma_attr;
  
+                 (void) ql_el_trace_alloc(ha);
+ 
+                 progress |= QL_SOFT_STATE_ALLOCED;
+ 
                  /* Get extended logging and dump flags. */
                  ql_common_properties(ha);
  
+                 qlc_fm_init(ha);
+                 progress |= QL_FCA_INIT_FM;
+ 
+                 ha->io_dma_attr = ha->bit32_io_dma_attr;
+ 
                  if (strcmp(ddi_driver_name(ddi_get_parent(dip)),
                      "sbus") == 0) {
!                         EL(ha, "%s SBUS card detected\n", QL_NAME);
                          ha->cfg_flags |= CFG_SBUS_CARD;
                  }
  
                  ha->dev = kmem_zalloc(sizeof (*ha->dev) *
                      DEVICE_HEAD_LIST_SIZE, KM_SLEEP);
  
                  ha->ub_array = kmem_zalloc(sizeof (*ha->ub_array) *
                      QL_UB_LIMIT, KM_SLEEP);
  
                  ha->adapter_stats = kmem_zalloc(sizeof (*ha->adapter_stats),
                      KM_SLEEP);
  
                  (void) ddi_pathname(dip, buf);
!                 ha->devpath = kmem_zalloc(strlen(buf) + 1, KM_SLEEP);
                  if (ha->devpath == NULL) {
                          EL(ha, "devpath mem alloc failed\n");
                  } else {
                          (void) strcpy(ha->devpath, buf);
                          EL(ha, "devpath is: %s\n", ha->devpath);
*** 966,976 ****
                                  cmn_err(CE_WARN, "%s(%d): Unable to get PCI "
                                      "address registers", QL_NAME, instance);
                                  goto attach_failed;
                          } else {
                                  ha->pci_bus_addr = ptr[0];
!                                 ha->function_number = (uint8_t)
                                      (ha->pci_bus_addr >> 8 & 7);
                                  ddi_prop_free(ptr);
                          }
  
                          /*
--- 1019,1029 ----
                                  cmn_err(CE_WARN, "%s(%d): Unable to get PCI "
                                      "address registers", QL_NAME, instance);
                                  goto attach_failed;
                          } else {
                                  ha->pci_bus_addr = ptr[0];
!                                 ha->pci_function_number = (uint8_t)
                                      (ha->pci_bus_addr >> 8 & 7);
                                  ddi_prop_free(ptr);
                          }
  
                          /*
*** 995,1004 ****
--- 1048,1065 ----
                           * 0x2   32-bit Memory Space address
                           * 0x3   64-bit Memory Space address
                           */
                          size = ql_pci_config_get32(ha, PCI_CONF_BASE0) & BIT_0 ?
                              2 : 1;
+ 
+                         if (qlc_fm_check_acc_handle(ha, ha->pci_handle)
+                             != DDI_FM_OK) {
+                                 qlc_fm_report_err_impact(ha,
+                                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
+                                 goto attach_failed;
+                         }
+ 
                          if (ddi_dev_regsize(dip, size, ®size) !=
                              DDI_SUCCESS ||
                              ddi_regs_map_setup(dip, size, &ha->iobase,
                              0, regsize, &ql_dev_acc_attr, &ha->dev_handle) !=
                              DDI_SUCCESS) {
*** 1006,1015 ****
--- 1067,1083 ----
                                      "failed", QL_NAME, instance);
                                  goto attach_failed;
                          }
                          progress |= QL_REGS_MAPPED;
  
+                         if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
+                             != DDI_FM_OK) {
+                                 qlc_fm_report_err_impact(ha,
+                                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
+                                 goto attach_failed;
+                         }
+ 
                          /*
                           * We need I/O space mappings for 23xx HBAs for
                           * loading flash (FCode). The chip has a bug due to
                           * which loading flash fails through mem space
                           * mappings in PCI-X mode.
*** 1028,1039 ****
--- 1096,1114 ----
                                              "setup(I/O) failed", QL_NAME,
                                              instance);
                                          goto attach_failed;
                                  }
                                  progress |= QL_IOMAP_IOBASE_MAPPED;
+ 
+                                 if (qlc_fm_check_acc_handle(ha,
+                                     ha->iomap_dev_handle) != DDI_FM_OK) {
+                                         qlc_fm_report_err_impact(ha,
+                                             QL_FM_EREPORT_ACC_HANDLE_CHECK);
+                                         goto attach_failed;
                                  }
                          }
+                 }
  
                  ha->subsys_id = (uint16_t)ql_pci_config_get16(ha,
                      PCI_CONF_SUBSYSID);
                  ha->subven_id = (uint16_t)ql_pci_config_get16(ha,
                      PCI_CONF_SUBVENID);
*** 1053,1075 ****
                  case 0x2312:
                  case 0x2322:
                  case 0x6312:
                  case 0x6322:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
!                                 ha->flags |= FUNCTION_1;
                          }
!                         if ((ha->device_id == 0x6322) ||
!                             (ha->device_id == 0x2322)) {
!                                 ha->cfg_flags |= CFG_CTRL_6322;
                                  ha->fw_class = 0x6322;
                                  ha->risc_dump_size = QL_6322_FW_DUMP_SIZE;
                          } else {
!                                 ha->cfg_flags |= CFG_CTRL_2300;
                                  ha->fw_class = 0x2300;
                                  ha->risc_dump_size = QL_2300_FW_DUMP_SIZE;
                          }
                          ha->reg_off = ®_off_2300;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->fcp_cmd = ql_command_iocb;
                          ha->ip_cmd = ql_ip_iocb;
--- 1128,1152 ----
                  case 0x2312:
                  case 0x2322:
                  case 0x6312:
                  case 0x6322:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
!                                 ha->function_number = 1;
                          }
!                         if (ha->device_id == 0x2322 ||
!                             ha->device_id == 0x6322) {
!                                 ha->cfg_flags |= CFG_CTRL_63XX;
                                  ha->fw_class = 0x6322;
                                  ha->risc_dump_size = QL_6322_FW_DUMP_SIZE;
                          } else {
!                                 ha->cfg_flags |= CFG_CTRL_23XX;
                                  ha->fw_class = 0x2300;
                                  ha->risc_dump_size = QL_2300_FW_DUMP_SIZE;
                          }
                          ha->reg_off = ®_off_2300;
+                         ha->interrupt_count = 1;
+                         ha->osc_max_cnt = 1024;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->fcp_cmd = ql_command_iocb;
                          ha->ip_cmd = ql_ip_iocb;
*** 1082,1093 ****
                                  ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
                          }
                          break;
  
                  case 0x2200:
!                         ha->cfg_flags |= CFG_CTRL_2200;
                          ha->reg_off = ®_off_2200;
                          ha->fw_class = 0x2200;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->risc_dump_size = QL_2200_FW_DUMP_SIZE;
--- 1159,1172 ----
                                  ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
                          }
                          break;
  
                  case 0x2200:
!                         ha->cfg_flags |= CFG_CTRL_22XX;
                          ha->reg_off = ®_off_2200;
+                         ha->interrupt_count = 1;
+                         ha->osc_max_cnt = 1024;
                          ha->fw_class = 0x2200;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->risc_dump_size = QL_2200_FW_DUMP_SIZE;
*** 1107,1126 ****
                  case 0x2432:
                  case 0x5422:
                  case 0x5432:
                  case 0x8432:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
!                                 ha->flags |= FUNCTION_1;
                          }
!                         ha->cfg_flags |= CFG_CTRL_2422;
                          if (ha->device_id == 0x8432) {
                                  ha->cfg_flags |= CFG_CTRL_MENLO;
                          } else {
                                  ha->flags |= VP_ENABLED;
                          }
  
                          ha->reg_off = ®_off_2400_2500;
                          ha->fw_class = 0x2400;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->risc_dump_size = QL_24XX_FW_DUMP_SIZE;
--- 1186,1208 ----
                  case 0x2432:
                  case 0x5422:
                  case 0x5432:
                  case 0x8432:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
!                                 ha->function_number = 1;
                          }
!                         ha->cfg_flags |= CFG_CTRL_24XX;
                          if (ha->device_id == 0x8432) {
                                  ha->cfg_flags |= CFG_CTRL_MENLO;
                          } else {
                                  ha->flags |= VP_ENABLED;
+                                 ha->max_vports = MAX_24_VIRTUAL_PORTS;
                          }
  
                          ha->reg_off = ®_off_2400_2500;
+                         ha->interrupt_count = 2;
+                         ha->osc_max_cnt = 2048;
                          ha->fw_class = 0x2400;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->risc_dump_size = QL_24XX_FW_DUMP_SIZE;
*** 1133,1211 ****
                          break;
  
                  case 0x2522:
                  case 0x2532:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
!                                 ha->flags |= FUNCTION_1;
                          }
                          ha->cfg_flags |= CFG_CTRL_25XX;
                          ha->flags |= VP_ENABLED;
!                         ha->fw_class = 0x2500;
                          ha->reg_off = ®_off_2400_2500;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
                          ha->fcp_cmd = ql_command_24xx_iocb;
-                         ha->ip_cmd = ql_ip_24xx_iocb;
                          ha->ms_cmd = ql_ms_24xx_iocb;
                          ha->els_cmd = ql_els_24xx_iocb;
                          ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
                          ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
                          break;
  
                  case 0x8001:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 4) {
!                                 ha->flags |= FUNCTION_1;
                          }
                          ha->cfg_flags |= CFG_CTRL_81XX;
                          ha->flags |= VP_ENABLED;
!                         ha->fw_class = 0x8100;
                          ha->reg_off = ®_off_2400_2500;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
!                         ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
                          ha->fcp_cmd = ql_command_24xx_iocb;
-                         ha->ip_cmd = ql_ip_24xx_iocb;
                          ha->ms_cmd = ql_ms_24xx_iocb;
                          ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
                          ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
                          break;
  
                  case 0x8021:
!                         if (ha->function_number & BIT_0) {
!                                 ha->flags |= FUNCTION_1;
                          }
!                         ha->cfg_flags |= CFG_CTRL_8021;
                          ha->reg_off = ®_off_8021;
                          ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
                          ha->fcp_cmd = ql_command_24xx_iocb;
                          ha->ms_cmd = ql_ms_24xx_iocb;
                          ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
                          ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
  
                          ha->nx_pcibase = ha->iobase;
!                         ha->iobase += 0xBC000 + (ha->function_number << 11);
                          ha->iomap_iobase += 0xBC000 +
!                             (ha->function_number << 11);
  
                          /* map doorbell */
                          if (ddi_dev_regsize(dip, 2, ®size) != DDI_SUCCESS ||
                              ddi_regs_map_setup(dip, 2, &ha->db_iobase,
!                             0, regsize, &ql_dev_acc_attr, &ha->db_dev_handle) !=
                              DDI_SUCCESS) {
                                  cmn_err(CE_WARN, "%s(%d): regs_map_setup"
                                      "(doorbell) failed", QL_NAME, instance);
                                  goto attach_failed;
                          }
                          progress |= QL_DB_IOBASE_MAPPED;
  
                          ha->nx_req_in = (uint32_t *)(ha->db_iobase +
!                             (ha->function_number << 12));
                          ha->db_read = ha->nx_pcibase + (512 * 1024) +
!                             (ha->function_number * 8);
  
                          ql_8021_update_crb_int_ptr(ha);
                          ql_8021_set_drv_active(ha);
                          break;
  
--- 1215,1389 ----
                          break;
  
                  case 0x2522:
                  case 0x2532:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 2) {
!                                 ha->function_number = 1;
                          }
                          ha->cfg_flags |= CFG_CTRL_25XX;
                          ha->flags |= VP_ENABLED;
!                         ha->max_vports = MAX_25_VIRTUAL_PORTS;
                          ha->reg_off = ®_off_2400_2500;
+                         ha->mbar_queue_offset = MBAR2_REG_OFFSET;
+                         ha->interrupt_count = 2;
+                         ha->osc_max_cnt = 2048;
+                         ha->fw_class = 0x2500;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
                          ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
                          ha->fcp_cmd = ql_command_24xx_iocb;
                          ha->ms_cmd = ql_ms_24xx_iocb;
                          ha->els_cmd = ql_els_24xx_iocb;
                          ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
                          ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
+                         if (ql_multi_queue_support(ha) == QL_SUCCESS) {
+                                 ha->flags |= MULTI_QUEUE;
+                         }
                          break;
  
+                 case 0x2031:
+                         /* Get queue pointer memory mapped registers */
+                         if (ddi_dev_regsize(dip, 3, ®size) != DDI_SUCCESS ||
+                             ddi_regs_map_setup(dip, 3, &ha->mbar,
+                             0, regsize, &ql_dev_acc_attr,
+                             &ha->mbar_dev_handle) != DDI_SUCCESS) {
+                                 cmn_err(CE_WARN, "%s(%d): regs_map_setup"
+                                     "(mbar) failed", QL_NAME, instance);
+                                 goto attach_failed;
+                         }
+                         ha->mbar_size = (uint32_t)regsize;
+ 
+                         if (ha->pci_function_number != 0 &&
+                             ha->pci_function_number != 2) {
+                                 ha->function_number = 1;
+                         }
+                         ha->cfg_flags |= CFG_CTRL_83XX;
+                         ha->flags |= VP_ENABLED | MULTI_QUEUE;
+                         ha->max_vports = MAX_83_VIRTUAL_PORTS;
+                         ha->reg_off = ®_off_2700_8300;
+                         ha->mbar_queue_offset = MBAR2_REG_OFFSET;
+                         ha->interrupt_count = 2;
+                         ha->osc_max_cnt = 2048;
+                         ha->fw_class = 0x8301fc;
+                         if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
+                                 goto attach_failed;
+                         }
+                         ha->risc_dump_size = QL_83XX_FW_DUMP_SIZE;
+                         ha->fcp_cmd = ql_command_24xx_iocb;
+                         ha->ms_cmd = ql_ms_24xx_iocb;
+                         ha->els_cmd = ql_els_24xx_iocb;
+                         ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
+                         ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
+                         break;
+ 
+                 case 0x2071:
+                 case 0x2261:
+                 case 0x2271:
+                         /* Get queue pointer memory mapped registers */
+                         if (ddi_dev_regsize(dip, 3, ®size) != DDI_SUCCESS ||
+                             ddi_regs_map_setup(dip, 3, &ha->mbar,
+                             0, regsize, &ql_dev_acc_attr,
+                             &ha->mbar_dev_handle) != DDI_SUCCESS) {
+                                 cmn_err(CE_WARN, "%s(%d): regs_map_setup"
+                                     "(mbar) failed", QL_NAME, instance);
+                                 goto attach_failed;
+                         }
+                         ha->mbar_size = (uint32_t)regsize;
+ 
+                         ha->function_number = ha->pci_function_number;
+                         ha->cfg_flags |= CFG_CTRL_27XX;
+                         ha->flags |= VP_ENABLED | MULTI_QUEUE |
+                             QUEUE_SHADOW_PTRS;
+                         ha->max_vports = MAX_27_VIRTUAL_PORTS;
+                         ha->reg_off = ®_off_2700_8300;
+                         ha->mbar_queue_offset = MBAR2_REG_OFFSET;
+                         ha->interrupt_count = 2;
+                         ha->osc_max_cnt = 2048;
+                         ha->fw_class = 0x2700;
+                         if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
+                                 goto attach_failed;
+                         }
+                         ha->risc_dump_size = QL_27XX_FW_DUMP_SIZE;
+                         ha->fcp_cmd = ql_command_24xx_iocb;
+                         ha->ms_cmd = ql_ms_24xx_iocb;
+                         ha->els_cmd = ql_els_24xx_iocb;
+                         ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
+                         ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
+                         break;
+ 
                  case 0x8001:
                          if (ql_pci_config_get8(ha, PCI_CONF_IPIN) == 4) {
!                                 ha->function_number = 1;
                          }
                          ha->cfg_flags |= CFG_CTRL_81XX;
                          ha->flags |= VP_ENABLED;
!                         ha->max_vports = MAX_81XX_VIRTUAL_PORTS;
                          ha->reg_off = ®_off_2400_2500;
+                         ha->mbar_queue_offset = MBAR2_REG_OFFSET;
+                         ha->interrupt_count = 2;
+                         ha->osc_max_cnt = 2048;
+                         ha->fw_class = 0x8100;
                          if (ql_fwmodule_resolve(ha) != QL_SUCCESS) {
                                  goto attach_failed;
                          }
!                         ha->risc_dump_size = QL_81XX_FW_DUMP_SIZE;
                          ha->fcp_cmd = ql_command_24xx_iocb;
                          ha->ms_cmd = ql_ms_24xx_iocb;
                          ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
                          ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
+                         if (ql_multi_queue_support(ha) == QL_SUCCESS) {
+                                 ha->flags |= MULTI_QUEUE;
+                         }
                          break;
  
                  case 0x8021:
!                         if (ha->pci_function_number & BIT_0) {
!                                 ha->function_number = 1;
                          }
!                         ha->cfg_flags |= CFG_CTRL_82XX;
!                         ha->flags |= VP_ENABLED;
!                         ha->max_vports = MAX_8021_VIRTUAL_PORTS;
                          ha->reg_off = ®_off_8021;
+                         ha->interrupt_count = 2;
+                         ha->osc_max_cnt = 2048;
                          ha->risc_dump_size = QL_25XX_FW_DUMP_SIZE;
                          ha->fcp_cmd = ql_command_24xx_iocb;
                          ha->ms_cmd = ql_ms_24xx_iocb;
                          ha->cmd_segs = CMD_TYPE_7_DATA_SEGMENTS;
                          ha->cmd_cont_segs = CONT_TYPE_1_DATA_SEGMENTS;
+                         ha->io_dma_attr.dma_attr_flags |=
+                             DDI_DMA_RELAXED_ORDERING;
  
                          ha->nx_pcibase = ha->iobase;
!                         ha->iobase += 0xBC000 + (ha->pci_function_number << 11);
                          ha->iomap_iobase += 0xBC000 +
!                             (ha->pci_function_number << 11);
  
                          /* map doorbell */
                          if (ddi_dev_regsize(dip, 2, ®size) != DDI_SUCCESS ||
                              ddi_regs_map_setup(dip, 2, &ha->db_iobase,
!                             0, regsize, &ql_dev_acc_attr,
!                             &ha->db_dev_handle) !=
                              DDI_SUCCESS) {
                                  cmn_err(CE_WARN, "%s(%d): regs_map_setup"
                                      "(doorbell) failed", QL_NAME, instance);
                                  goto attach_failed;
                          }
                          progress |= QL_DB_IOBASE_MAPPED;
  
+                         if (qlc_fm_check_acc_handle(ha, ha->db_dev_handle)
+                             != DDI_FM_OK) {
+                                 qlc_fm_report_err_impact(ha,
+                                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
+                                 goto attach_failed;
+                         }
+ 
                          ha->nx_req_in = (uint32_t *)(ha->db_iobase +
!                             (ha->pci_function_number << 12));
                          ha->db_read = ha->nx_pcibase + (512 * 1024) +
!                             (ha->pci_function_number * 8);
  
                          ql_8021_update_crb_int_ptr(ha);
                          ql_8021_set_drv_active(ha);
                          break;
  
*** 1213,1271 ****
                          cmn_err(CE_WARN, "%s(%d): Unsupported device id: %x",
                              QL_NAME, instance, ha->device_id);
                          goto attach_failed;
                  }
  
!                 /* Setup hba buffer. */
  
!                 size = CFG_IST(ha, CFG_CTRL_24258081) ?
!                     (REQUEST_QUEUE_SIZE + RESPONSE_QUEUE_SIZE) :
!                     (REQUEST_QUEUE_SIZE + RESPONSE_QUEUE_SIZE +
!                     RCVBUF_QUEUE_SIZE);
  
!                 if (ql_get_dma_mem(ha, &ha->hba_buf, size, LITTLE_ENDIAN_DMA,
!                     QL_DMA_RING_ALIGN) != QL_SUCCESS) {
                          cmn_err(CE_WARN, "%s(%d): request queue DMA memory "
                              "alloc failed", QL_NAME, instance);
                          goto attach_failed;
                  }
                  progress |= QL_HBA_BUFFER_SETUP;
  
-                 /* Setup buffer pointers. */
-                 ha->request_dvma = ha->hba_buf.cookie.dmac_laddress +
-                     REQUEST_Q_BUFFER_OFFSET;
-                 ha->request_ring_bp = (struct cmd_entry *)
-                     ((caddr_t)ha->hba_buf.bp + REQUEST_Q_BUFFER_OFFSET);
- 
-                 ha->response_dvma = ha->hba_buf.cookie.dmac_laddress +
-                     RESPONSE_Q_BUFFER_OFFSET;
-                 ha->response_ring_bp = (struct sts_entry *)
-                     ((caddr_t)ha->hba_buf.bp + RESPONSE_Q_BUFFER_OFFSET);
- 
-                 ha->rcvbuf_dvma = ha->hba_buf.cookie.dmac_laddress +
-                     RCVBUF_Q_BUFFER_OFFSET;
-                 ha->rcvbuf_ring_bp = (struct rcvbuf *)
-                     ((caddr_t)ha->hba_buf.bp + RCVBUF_Q_BUFFER_OFFSET);
- 
                  /* Allocate resource for QLogic IOCTL */
                  (void) ql_alloc_xioctl_resource(ha);
  
!                 /* Setup interrupts */
!                 if ((rval = ql_setup_interrupts(ha)) != DDI_SUCCESS) {
!                         cmn_err(CE_WARN, "%s(%d): Failed to add interrupt, "
!                             "rval=%xh", QL_NAME, instance, rval);
                          goto attach_failed;
                  }
  
!                 progress |= (QL_INTR_ADDED | QL_MUTEX_CV_INITED);
  
!                 if (ql_nvram_cache_desc_ctor(ha) != DDI_SUCCESS) {
!                         cmn_err(CE_WARN, "%s(%d): can't setup nvram cache",
                              QL_NAME, instance);
                          goto attach_failed;
                  }
  
                  /*
                   * Allocate an N Port information structure
                   * for use when in P2P topology.
                   */
                  ha->n_port = (ql_n_port_info_t *)
--- 1391,1441 ----
                          cmn_err(CE_WARN, "%s(%d): Unsupported device id: %x",
                              QL_NAME, instance, ha->device_id);
                          goto attach_failed;
                  }
  
!                 ha->outstanding_cmds = kmem_zalloc(
!                     sizeof (*ha->outstanding_cmds) * ha->osc_max_cnt,
!                     KM_SLEEP);
  
!                 /* Setup interrupts */
!                 if ((rval = ql_setup_interrupts(ha)) != DDI_SUCCESS) {
!                         cmn_err(CE_WARN, "%s(%d): Failed to add interrupt, "
!                             "rval=%xh", QL_NAME, instance, rval);
!                         goto attach_failed;
!                 }
  
!                 progress |= (QL_INTR_ADDED | QL_MUTEX_CV_INITED);
! 
!                 /* Setup hba buffer. */
!                 if (ql_create_queues(ha) != QL_SUCCESS) {
                          cmn_err(CE_WARN, "%s(%d): request queue DMA memory "
                              "alloc failed", QL_NAME, instance);
                          goto attach_failed;
                  }
                  progress |= QL_HBA_BUFFER_SETUP;
  
                  /* Allocate resource for QLogic IOCTL */
                  (void) ql_alloc_xioctl_resource(ha);
  
! 
!                 if (ql_nvram_cache_desc_ctor(ha) != DDI_SUCCESS) {
!                         cmn_err(CE_WARN, "%s(%d): can't setup nvram cache",
!                             QL_NAME, instance);
                          goto attach_failed;
                  }
  
!                 progress |= QL_NVRAM_CACHE_CREATED;
  
!                 if (ql_plogi_params_desc_ctor(ha) != DDI_SUCCESS) {
!                         cmn_err(CE_WARN, "%s(%d): can't setup plogi params",
                              QL_NAME, instance);
                          goto attach_failed;
                  }
  
+                 progress |= QL_PLOGI_PARAMS_CREATED;
+ 
                  /*
                   * Allocate an N Port information structure
                   * for use when in P2P topology.
                   */
                  ha->n_port = (ql_n_port_info_t *)
*** 1352,1379 ****
                  if (ha->fw_major_version == 0 && ha->fw_minor_version == 0 &&
                      ha->fw_subminor_version == 0) {
                          cmn_err(CE_NOTE, "!%s(%d): Firmware not loaded",
                              QL_NAME, ha->instance);
                  } else {
!                         int     rval;
                          char    ver_fmt[256];
  
!                         rval = (int)snprintf(ver_fmt, (size_t)sizeof (ver_fmt),
                              "Firmware version %d.%d.%d", ha->fw_major_version,
                              ha->fw_minor_version, ha->fw_subminor_version);
  
                          if (CFG_IST(ha, CFG_CTRL_81XX)) {
!                                 rval = (int)snprintf(ver_fmt + rval,
                                      (size_t)sizeof (ver_fmt),
                                      ", MPI fw version %d.%d.%d",
                                      ha->mpi_fw_major_version,
                                      ha->mpi_fw_minor_version,
                                      ha->mpi_fw_subminor_version);
  
                                  if (ha->subsys_id == 0x17B ||
                                      ha->subsys_id == 0x17D) {
!                                         (void) snprintf(ver_fmt + rval,
                                              (size_t)sizeof (ver_fmt),
                                              ", PHY fw version %d.%d.%d",
                                              ha->phy_fw_major_version,
                                              ha->phy_fw_minor_version,
                                              ha->phy_fw_subminor_version);
--- 1522,1549 ----
                  if (ha->fw_major_version == 0 && ha->fw_minor_version == 0 &&
                      ha->fw_subminor_version == 0) {
                          cmn_err(CE_NOTE, "!%s(%d): Firmware not loaded",
                              QL_NAME, ha->instance);
                  } else {
!                         int     rval, rval1;
                          char    ver_fmt[256];
  
!                         rval1 = (int)snprintf(ver_fmt, (size_t)sizeof (ver_fmt),
                              "Firmware version %d.%d.%d", ha->fw_major_version,
                              ha->fw_minor_version, ha->fw_subminor_version);
  
                          if (CFG_IST(ha, CFG_CTRL_81XX)) {
!                                 rval = (int)snprintf(ver_fmt + rval1,
                                      (size_t)sizeof (ver_fmt),
                                      ", MPI fw version %d.%d.%d",
                                      ha->mpi_fw_major_version,
                                      ha->mpi_fw_minor_version,
                                      ha->mpi_fw_subminor_version);
  
                                  if (ha->subsys_id == 0x17B ||
                                      ha->subsys_id == 0x17D) {
!                                         (void) snprintf(ver_fmt + rval1 + rval,
                                              (size_t)sizeof (ver_fmt),
                                              ", PHY fw version %d.%d.%d",
                                              ha->phy_fw_major_version,
                                              ha->phy_fw_minor_version,
                                              ha->phy_fw_subminor_version);
*** 1420,1466 ****
                  progress |= QL_FCA_TRAN_ALLOCED;
  
                  /* fill in the structure */
                  tran->fca_numports = 1;
                  tran->fca_version = FCTL_FCA_MODREV_5;
!                 if (CFG_IST(ha, CFG_CTRL_2422)) {
!                         tran->fca_num_npivports = MAX_24_VIRTUAL_PORTS;
!                 } else if (CFG_IST(ha, CFG_CTRL_2581)) {
!                         tran->fca_num_npivports = MAX_25_VIRTUAL_PORTS;
!                 }
                  bcopy(ha->loginparams.node_ww_name.raw_wwn,
                      tran->fca_perm_pwwn.raw_wwn, 8);
  
!                 EL(ha, "FCA version %d\n", tran->fca_version);
  
                  /* Specify the amount of space needed in each packet */
                  tran->fca_pkt_size = sizeof (ql_srb_t);
  
                  /* command limits are usually dictated by hardware */
!                 tran->fca_cmd_max = MAX_OUTSTANDING_COMMANDS;
  
                  /* dmaattr are static, set elsewhere. */
!                 if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
!                         tran->fca_dma_attr = &ql_64bit_io_dma_attr;
!                         tran->fca_dma_fcp_cmd_attr = &ql_64fcp_cmd_dma_attr;
!                         tran->fca_dma_fcp_rsp_attr = &ql_64fcp_rsp_dma_attr;
!                         tran->fca_dma_fcp_data_attr = &ql_64fcp_data_dma_attr;
!                         tran->fca_dma_fcsm_cmd_attr = &ql_64fcsm_cmd_dma_attr;
!                         tran->fca_dma_fcsm_rsp_attr = &ql_64fcsm_rsp_dma_attr;
!                         tran->fca_dma_fcip_cmd_attr = &ql_64fcip_cmd_dma_attr;
!                         tran->fca_dma_fcip_rsp_attr = &ql_64fcip_rsp_dma_attr;
!                 } else {
!                         tran->fca_dma_attr = &ql_32bit_io_dma_attr;
!                         tran->fca_dma_fcp_cmd_attr = &ql_32fcp_cmd_dma_attr;
!                         tran->fca_dma_fcp_rsp_attr = &ql_32fcp_rsp_dma_attr;
!                         tran->fca_dma_fcp_data_attr = &ql_32fcp_data_dma_attr;
!                         tran->fca_dma_fcsm_cmd_attr = &ql_32fcsm_cmd_dma_attr;
!                         tran->fca_dma_fcsm_rsp_attr = &ql_32fcsm_rsp_dma_attr;
!                         tran->fca_dma_fcip_cmd_attr = &ql_32fcip_cmd_dma_attr;
!                         tran->fca_dma_fcip_rsp_attr = &ql_32fcip_rsp_dma_attr;
!                 }
! 
                  tran->fca_acc_attr = &ql_dev_acc_attr;
                  tran->fca_iblock = &(ha->iblock_cookie);
  
                  /* the remaining values are simply function vectors */
                  tran->fca_bind_port = ql_bind_port;
--- 1590,1663 ----
                  progress |= QL_FCA_TRAN_ALLOCED;
  
                  /* fill in the structure */
                  tran->fca_numports = 1;
                  tran->fca_version = FCTL_FCA_MODREV_5;
!                 tran->fca_num_npivports = ha->max_vports ?
!                     ha->max_vports - 1 : 0;
                  bcopy(ha->loginparams.node_ww_name.raw_wwn,
                      tran->fca_perm_pwwn.raw_wwn, 8);
  
!                 if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
!                         ha->io_dma_attr = ha->bit64_io_dma_attr;
!                         ha->fcsm_cmd_dma_attr = ha->bit64_io_dma_attr;
!                         ha->fcsm_rsp_dma_attr = ha->bit64_io_dma_attr;
!                         ha->fcip_cmd_dma_attr = ha->bit64_io_dma_attr;
!                         ha->fcip_rsp_dma_attr = ha->bit64_io_dma_attr;
!                         ha->fcp_cmd_dma_attr = ha->bit64_io_dma_attr;
!                         ha->fcp_rsp_dma_attr = ha->bit64_io_dma_attr;
!                         ha->fcp_data_dma_attr = ha->bit64_io_dma_attr;
!                 } else {
!                         ha->io_dma_attr = ha->bit32_io_dma_attr;
!                         ha->fcsm_cmd_dma_attr = ha->bit32_io_dma_attr;
!                         ha->fcsm_rsp_dma_attr = ha->bit32_io_dma_attr;
!                         ha->fcip_cmd_dma_attr = ha->bit32_io_dma_attr;
!                         ha->fcip_rsp_dma_attr = ha->bit32_io_dma_attr;
!                         ha->fcp_cmd_dma_attr = ha->bit32_io_dma_attr;
!                         ha->fcp_rsp_dma_attr = ha->bit32_io_dma_attr;
!                         ha->fcp_data_dma_attr = ha->bit32_io_dma_attr;
!                 }
!                 ha->fcsm_cmd_dma_attr.dma_attr_sgllen = QL_FCSM_CMD_SGLLEN;
!                 ha->fcsm_rsp_dma_attr.dma_attr_sgllen = QL_FCSM_RSP_SGLLEN;
!                 ha->fcip_cmd_dma_attr.dma_attr_sgllen = QL_FCIP_CMD_SGLLEN;
!                 ha->fcip_rsp_dma_attr.dma_attr_sgllen = QL_FCIP_RSP_SGLLEN;
!                 ha->fcp_cmd_dma_attr.dma_attr_sgllen = QL_FCP_CMD_SGLLEN;
!                 ha->fcp_rsp_dma_attr.dma_attr_sgllen = QL_FCP_RSP_SGLLEN;
!                 if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                         ha->io_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                         ha->fcsm_cmd_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                         ha->fcsm_rsp_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                         ha->fcip_cmd_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                         ha->fcip_rsp_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                         ha->fcp_cmd_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                         ha->fcp_rsp_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                         ha->fcp_data_dma_attr.dma_attr_flags |=
!                             DDI_DMA_RELAXED_ORDERING;
!                 }
  
                  /* Specify the amount of space needed in each packet */
                  tran->fca_pkt_size = sizeof (ql_srb_t);
  
                  /* command limits are usually dictated by hardware */
!                 tran->fca_cmd_max = ha->osc_max_cnt;
  
                  /* dmaattr are static, set elsewhere. */
!                 tran->fca_dma_attr = &ha->io_dma_attr;
!                 tran->fca_dma_fcp_cmd_attr = &ha->fcp_cmd_dma_attr;
!                 tran->fca_dma_fcp_rsp_attr = &ha->fcp_rsp_dma_attr;
!                 tran->fca_dma_fcp_data_attr = &ha->fcp_data_dma_attr;
!                 tran->fca_dma_fcsm_cmd_attr = &ha->fcsm_cmd_dma_attr;
!                 tran->fca_dma_fcsm_rsp_attr = &ha->fcsm_rsp_dma_attr;
!                 tran->fca_dma_fcip_cmd_attr = &ha->fcip_cmd_dma_attr;
!                 tran->fca_dma_fcip_rsp_attr = &ha->fcip_rsp_dma_attr;
                  tran->fca_acc_attr = &ql_dev_acc_attr;
                  tran->fca_iblock = &(ha->iblock_cookie);
  
                  /* the remaining values are simply function vectors */
                  tran->fca_bind_port = ql_bind_port;
*** 1478,1487 ****
--- 1675,1687 ----
                  tran->fca_abort = ql_abort;
                  tran->fca_reset = ql_reset;
                  tran->fca_port_manage = ql_port_manage;
                  tran->fca_get_device = ql_get_device;
  
+                 EL(ha, "Transport interface setup. FCA version %d\n",
+                     tran->fca_version);
+ 
                  /* give it to the FC transport */
                  if (fc_fca_attach(dip, tran) != DDI_SUCCESS) {
                          cmn_err(CE_WARN, "%s(%d): FCA attach failed", QL_NAME,
                              instance);
                          goto attach_failed;
*** 1495,1521 ****
                  GLOBAL_STATE_LOCK();
  
                  /* Add adapter structure to link list. */
                  ql_add_link_b(&ql_hba, &ha->hba);
  
                  /* Start one second driver timer. */
                  if (ql_timer_timeout_id == NULL) {
                          ql_timer_ticks = drv_usectohz(1000000);
                          ql_timer_timeout_id = timeout(ql_timer, (void *)0,
                              ql_timer_ticks);
                  }
  
-                 /* Release global state lock. */
-                 GLOBAL_STATE_UNLOCK();
- 
-                 /* Determine and populate HBA fru info */
-                 ql_setup_fruinfo(ha);
- 
                  /* Setup task_daemon thread. */
!                 (void) thread_create(NULL, 0, (void (*)())ql_task_daemon, ha,
!                     0, &p0, TS_RUN, minclsyspri);
  
                  progress |= QL_TASK_DAEMON_STARTED;
  
                  ddi_report_dev(dip);
  
                  /* Disable link reset in panic path */
--- 1695,1737 ----
                  GLOBAL_STATE_LOCK();
  
                  /* Add adapter structure to link list. */
                  ql_add_link_b(&ql_hba, &ha->hba);
  
+                 /* Determine and populate HBA fru info */
+                 ql_setup_fruinfo(ha);
+ 
+                 /* Release global state lock. */
+                 GLOBAL_STATE_UNLOCK();
+ 
                  /* Start one second driver timer. */
+                 GLOBAL_TIMER_LOCK();
                  if (ql_timer_timeout_id == NULL) {
                          ql_timer_ticks = drv_usectohz(1000000);
                          ql_timer_timeout_id = timeout(ql_timer, (void *)0,
                              ql_timer_ticks);
                  }
+                 GLOBAL_TIMER_UNLOCK();
  
                  /* Setup task_daemon thread. */
!                 (void) snprintf(taskq_name, sizeof (taskq_name),
!                     "qlc_%d_driver_thread", instance);
!                 ha->driver_thread_taskq = ddi_taskq_create(NULL, taskq_name, 1,
!                     TASKQ_DEFAULTPRI, 0);
!                 (void) ddi_taskq_dispatch(ha->driver_thread_taskq,
!                     ql_task_daemon, ha, DDI_SLEEP);
!                 ha->task_daemon_flags |= TASK_DAEMON_ALIVE_FLG;
  
+                 (void) snprintf(taskq_name, sizeof (taskq_name),
+                     "qlc_%d_comp_thd", instance);
+                 ha->completion_taskq = ddi_taskq_create(0, taskq_name,
+                     ha->completion_thds, maxclsyspri, 0);
+                 for (size = 0; size < ha->completion_thds; size++) {
+                         (void) ddi_taskq_dispatch(ha->completion_taskq,
+                             ql_completion_thread, ha, DDI_SLEEP);
+                 }
+ 
                  progress |= QL_TASK_DAEMON_STARTED;
  
                  ddi_report_dev(dip);
  
                  /* Disable link reset in panic path */
*** 1523,1532 ****
--- 1739,1753 ----
  
                  rval = DDI_SUCCESS;
                  break;
  
  attach_failed:
+                 if (progress & QL_FCA_INIT_FM) {
+                         qlc_fm_fini(ha);
+                         progress &= ~QL_FCA_INIT_FM;
+                 }
+ 
                  if (progress & QL_FCA_ATTACH_DONE) {
                          (void) fc_fca_detach(dip);
                          progress &= ~QL_FCA_ATTACH_DONE;
                  }
  
*** 1548,1570 ****
                  if (progress & QL_N_PORT_INFO_CREATED) {
                          kmem_free(ha->n_port, sizeof (ql_n_port_info_t));
                          progress &= ~QL_N_PORT_INFO_CREATED;
                  }
  
!                 if (progress & QL_TASK_DAEMON_STARTED) {
!                         TASK_DAEMON_LOCK(ha);
  
!                         ha->task_daemon_flags |= TASK_DAEMON_STOP_FLG;
  
!                         cv_signal(&ha->cv_task_daemon);
  
!                         /* Release task daemon lock. */
!                         TASK_DAEMON_UNLOCK(ha);
  
!                         /* Wait for for task daemon to stop running. */
!                         while (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
                                  ql_delay(ha, 10000);
                          }
                          progress &= ~QL_TASK_DAEMON_STARTED;
                  }
  
                  if (progress & QL_DB_IOBASE_MAPPED) {
--- 1769,1816 ----
                  if (progress & QL_N_PORT_INFO_CREATED) {
                          kmem_free(ha->n_port, sizeof (ql_n_port_info_t));
                          progress &= ~QL_N_PORT_INFO_CREATED;
                  }
  
!                 if (progress & QL_PLOGI_PARAMS_CREATED) {
!                         (void) ql_plogi_params_desc_dtor(ha);
!                         progress &= ~QL_PLOGI_PARAMS_CREATED;
!                 }
  
!                 if (progress & QL_NVRAM_CACHE_CREATED) {
!                         (void) ql_nvram_cache_desc_dtor(ha);
!                         progress &= ~QL_NVRAM_CACHE_CREATED;
!                 }
  
!                 if (progress & QL_TASK_DAEMON_STARTED) {
!                         if (ha->driver_thread_taskq) {
!                                 while (ha->task_daemon_flags &
!                                     TASK_DAEMON_ALIVE_FLG) {
!                                         /* Delay for 1 tick (10 ms). */
!                                         ql_awaken_task_daemon(ha, NULL,
!                                             TASK_DAEMON_STOP_FLG, 0);
!                                         delay(1);
!                                 }
!                                 ha->task_daemon_flags &= ~TASK_DAEMON_STOP_FLG;
  
!                                 ddi_taskq_destroy(ha->driver_thread_taskq);
!                                 ha->driver_thread_taskq = NULL;
!                         }
!                         if (ha->completion_taskq) {
!                                 ADAPTER_STATE_LOCK(ha);
!                                 ha->flags |= COMP_THD_TERMINATE;
!                                 ADAPTER_STATE_UNLOCK(ha);
  
!                                 do {
!                                         COMP_Q_LOCK(ha);
!                                         cv_broadcast(&ha->cv_comp_thread);
!                                         COMP_Q_UNLOCK(ha);
                                          ql_delay(ha, 10000);
+                                 } while (ha->comp_thds_active != 0);
+ 
+                                 ddi_taskq_destroy(ha->completion_taskq);
+                                 ha->completion_taskq = NULL;
                          }
                          progress &= ~QL_TASK_DAEMON_STARTED;
                  }
  
                  if (progress & QL_DB_IOBASE_MAPPED) {
*** 1574,1583 ****
--- 1820,1835 ----
                  }
                  if (progress & QL_IOMAP_IOBASE_MAPPED) {
                          ddi_regs_map_free(&ha->iomap_dev_handle);
                          progress &= ~QL_IOMAP_IOBASE_MAPPED;
                  }
+                 if (progress & QL_REGS_MAPPED) {
+                         if (ha->mbar_dev_handle) {
+                                 ddi_regs_map_free(&ha->mbar_dev_handle);
+                                 ha->mbar_dev_handle = 0;
+                         }
+                 }
  
                  if (progress & QL_CONFIG_SPACE_SETUP) {
                          if (CFG_IST(ha, CFG_SBUS_CARD)) {
                                  ddi_regs_map_free(&ha->sbus_config_handle);
                          } else {
*** 1596,1606 ****
                          ql_destroy_mutex(ha);
                          progress &= ~QL_MUTEX_CV_INITED;
                  }
  
                  if (progress & QL_HBA_BUFFER_SETUP) {
!                         ql_free_phys(ha, &ha->hba_buf);
                          progress &= ~QL_HBA_BUFFER_SETUP;
                  }
  
                  if (progress & QL_REGS_MAPPED) {
                          ddi_regs_map_free(&ha->dev_handle);
--- 1848,1858 ----
                          ql_destroy_mutex(ha);
                          progress &= ~QL_MUTEX_CV_INITED;
                  }
  
                  if (progress & QL_HBA_BUFFER_SETUP) {
!                         ql_delete_queues(ha);
                          progress &= ~QL_HBA_BUFFER_SETUP;
                  }
  
                  if (progress & QL_REGS_MAPPED) {
                          ddi_regs_map_free(&ha->dev_handle);
*** 1618,1630 ****
                              sizeof (*ha->adapter_stats));
  
                          kmem_free(ha->ub_array, sizeof (*ha->ub_array) *
                              QL_UB_LIMIT);
  
                          kmem_free(ha->outstanding_cmds,
                              sizeof (*ha->outstanding_cmds) *
!                             MAX_OUTSTANDING_COMMANDS);
  
                          if (ha->devpath != NULL) {
                                  kmem_free(ha->devpath,
                                      strlen(ha->devpath) + 1);
                          }
--- 1870,1884 ----
                              sizeof (*ha->adapter_stats));
  
                          kmem_free(ha->ub_array, sizeof (*ha->ub_array) *
                              QL_UB_LIMIT);
  
+                         if (ha->outstanding_cmds != NULL) {
                                  kmem_free(ha->outstanding_cmds,
                                      sizeof (*ha->outstanding_cmds) *
!                                     ha->osc_max_cnt);
!                         }
  
                          if (ha->devpath != NULL) {
                                  kmem_free(ha->devpath,
                                      strlen(ha->devpath) + 1);
                          }
*** 1637,1648 ****
                          }
  
                          if (ha->fw_module != NULL) {
                                  (void) ddi_modclose(ha->fw_module);
                          }
!                         (void) ql_el_trace_desc_dtor(ha);
!                         (void) ql_nvram_cache_desc_dtor(ha);
  
                          ddi_soft_state_free(ql_state, instance);
                          progress &= ~QL_SOFT_STATE_ALLOCED;
                  }
  
--- 1891,1901 ----
                          }
  
                          if (ha->fw_module != NULL) {
                                  (void) ddi_modclose(ha->fw_module);
                          }
!                         (void) ql_el_trace_dealloc(ha);
  
                          ddi_soft_state_free(ql_state, instance);
                          progress &= ~QL_SOFT_STATE_ALLOCED;
                  }
  
*** 1687,1720 ****
                          /* Wake up task_daemon. */
                          ql_awaken_task_daemon(ha, NULL, TASK_DAEMON_ALIVE_FLG,
                              0);
                  }
  
-                 /* Acquire global state lock. */
-                 GLOBAL_STATE_LOCK();
- 
                  /* Restart driver timer. */
                  if (ql_timer_timeout_id == NULL) {
                          ql_timer_timeout_id = timeout(ql_timer, (void *)0,
                              ql_timer_ticks);
                  }
  
-                 /* Release global state lock. */
-                 GLOBAL_STATE_UNLOCK();
- 
                  /* Wake up command start routine. */
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags &= ~ADAPTER_SUSPENDED;
                  ADAPTER_STATE_UNLOCK(ha);
  
-                 /*
-                  * Transport doesn't make FC discovery in polled
-                  * mode; So we need the daemon thread's services
-                  * right here.
-                  */
-                 (void) callb_generic_cpr(&ha->cprinfo, CB_CODE_CPR_RESUME);
- 
                  rval = DDI_SUCCESS;
  
                  /* Restart IP if it was running. */
                  if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) {
                          (void) ql_initialize_ip(ha);
--- 1940,1962 ----
                          /* Wake up task_daemon. */
                          ql_awaken_task_daemon(ha, NULL, TASK_DAEMON_ALIVE_FLG,
                              0);
                  }
  
                  /* Restart driver timer. */
+                 GLOBAL_TIMER_LOCK();
                  if (ql_timer_timeout_id == NULL) {
                          ql_timer_timeout_id = timeout(ql_timer, (void *)0,
                              ql_timer_ticks);
                  }
+                 GLOBAL_TIMER_LOCK();
  
                  /* Wake up command start routine. */
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags &= ~ADAPTER_SUSPENDED;
                  ADAPTER_STATE_UNLOCK(ha);
  
                  rval = DDI_SUCCESS;
  
                  /* Restart IP if it was running. */
                  if (ha->flags & IP_ENABLED && !(ha->flags & IP_INITIALIZED)) {
                          (void) ql_initialize_ip(ha);
*** 1731,1745 ****
  
          kmem_free(buf, MAXPATHLEN);
  
          if (rval != DDI_SUCCESS) {
                  /*EMPTY*/
!                 QL_PRINT_2(CE_CONT, "(%d): failed, rval = %xh\n",
                      ddi_get_instance(dip), rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ddi_get_instance(dip));
          }
  
          return (rval);
  }
  
--- 1973,1987 ----
  
          kmem_free(buf, MAXPATHLEN);
  
          if (rval != DDI_SUCCESS) {
                  /*EMPTY*/
!                 QL_PRINT_2(ha, "failed instance=%d, rval = %xh\n",
                      ddi_get_instance(dip), rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 1762,1829 ****
  static int
  ql_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
  {
          ql_adapter_state_t      *ha, *vha;
          ql_tgt_t                *tq;
-         int                     delay_cnt;
          uint16_t                index;
          ql_link_t               *link;
          char                    *buf;
          timeout_id_t            timer_id = NULL;
          int                     suspend, rval = DDI_SUCCESS;
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
                      ddi_get_instance(dip));
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): started, cmd=%xh\n", ha->instance, cmd);
  
          buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
  
          switch (cmd) {
          case DDI_DETACH:
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags |= (ADAPTER_SUSPENDED | ABORT_CMDS_LOOP_DOWN_TMO);
                  ADAPTER_STATE_UNLOCK(ha);
  
!                 TASK_DAEMON_LOCK(ha);
  
!                 if (ha->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) {
!                         ha->task_daemon_flags |= TASK_DAEMON_STOP_FLG;
!                         cv_signal(&ha->cv_task_daemon);
  
!                         TASK_DAEMON_UNLOCK(ha);
  
!                         (void) ql_wait_for_td_stop(ha);
  
!                         TASK_DAEMON_LOCK(ha);
!                         if (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
!                                 ha->task_daemon_flags &= ~TASK_DAEMON_STOP_FLG;
!                                 EL(ha, "failed, could not stop task daemon\n");
                          }
-                 }
-                 TASK_DAEMON_UNLOCK(ha);
  
-                 GLOBAL_STATE_LOCK();
- 
                  /* Disable driver timer if no adapters. */
                  if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
                      ql_hba.last == &ha->hba) {
                          timer_id = ql_timer_timeout_id;
                          ql_timer_timeout_id = NULL;
                  }
!                 ql_remove_link(&ql_hba, &ha->hba);
  
-                 GLOBAL_STATE_UNLOCK();
- 
                  if (timer_id) {
                          (void) untimeout(timer_id);
                  }
  
                  if (ha->pm_capable) {
                          if (pm_lower_power(dip, QL_POWER_COMPONENT,
                              PM_LEVEL_D3) != DDI_SUCCESS) {
                                  cmn_err(CE_WARN, "%s(%d): failed to lower the"
                                      " power", QL_NAME, ha->instance);
--- 2004,2090 ----
  static int
  ql_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
  {
          ql_adapter_state_t      *ha, *vha;
          ql_tgt_t                *tq;
          uint16_t                index;
          ql_link_t               *link;
          char                    *buf;
          timeout_id_t            timer_id = NULL;
          int                     suspend, rval = DDI_SUCCESS;
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "no adapter, instance=%d\n",
                      ddi_get_instance(dip));
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(ha, "started, cmd=%xh\n", cmd);
  
          buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
  
          switch (cmd) {
          case DDI_DETACH:
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags |= (ADAPTER_SUSPENDED | ABORT_CMDS_LOOP_DOWN_TMO);
                  ADAPTER_STATE_UNLOCK(ha);
  
!                 /* Wait for task thread to see suspend flag. */
!                 while (!(ha->task_daemon_flags & TASK_DAEMON_STALLED_FLG) &&
!                     ha->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) {
!                         ql_awaken_task_daemon(ha, NULL, 0, 0);
!                         /* Delay for 1 tick (10 milliseconds). */
!                         delay(1);
!                 }
  
!                 if (ha->driver_thread_taskq) {
!                         while (ha->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) {
!                                 /* Delay for 1 tick (10 milliseconds). */
!                                 ql_awaken_task_daemon(ha, NULL,
!                                     TASK_DAEMON_STOP_FLG, 0);
!                                 delay(1);
!                         }
!                         ha->task_daemon_flags &= ~TASK_DAEMON_STOP_FLG;
  
!                         ddi_taskq_destroy(ha->driver_thread_taskq);
!                         ha->driver_thread_taskq = NULL;
!                 }
  
!                 if (ha->completion_taskq) {
!                         ADAPTER_STATE_LOCK(ha);
!                         ha->flags |= COMP_THD_TERMINATE;
!                         ADAPTER_STATE_UNLOCK(ha);
  
!                         do {
!                                 COMP_Q_LOCK(ha);
!                                 cv_broadcast(&ha->cv_comp_thread);
!                                 COMP_Q_UNLOCK(ha);
!                                 ql_delay(ha, 10000);
!                         } while (ha->comp_thds_active != 0);
! 
!                         ddi_taskq_destroy(ha->completion_taskq);
!                         ha->completion_taskq = NULL;
                  }
  
                  /* Disable driver timer if no adapters. */
+                 GLOBAL_TIMER_LOCK();
                  if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
                      ql_hba.last == &ha->hba) {
                          timer_id = ql_timer_timeout_id;
                          ql_timer_timeout_id = NULL;
                  }
!                 GLOBAL_TIMER_UNLOCK();
  
                  if (timer_id) {
                          (void) untimeout(timer_id);
                  }
  
+                 GLOBAL_STATE_LOCK();
+                 ql_remove_link(&ql_hba, &ha->hba);
+                 GLOBAL_STATE_UNLOCK();
+ 
                  if (ha->pm_capable) {
                          if (pm_lower_power(dip, QL_POWER_COMPONENT,
                              PM_LEVEL_D3) != DDI_SUCCESS) {
                                  cmn_err(CE_WARN, "%s(%d): failed to lower the"
                                      " power", QL_NAME, ha->instance);
*** 1907,1917 ****
                  }
  
                  if (CFG_IST(ha, CFG_SBUS_CARD)) {
                          ddi_regs_map_free(&ha->sbus_config_handle);
                  } else {
!                         if (CFG_IST(ha, CFG_CTRL_8021)) {
                                  ql_8021_clr_drv_active(ha);
                                  ddi_regs_map_free(&ha->db_dev_handle);
                          }
                          if (ha->iomap_dev_handle != ha->dev_handle) {
                                  ddi_regs_map_free(&ha->iomap_dev_handle);
--- 2168,2178 ----
                  }
  
                  if (CFG_IST(ha, CFG_SBUS_CARD)) {
                          ddi_regs_map_free(&ha->sbus_config_handle);
                  } else {
!                         if (CFG_IST(ha, CFG_CTRL_82XX)) {
                                  ql_8021_clr_drv_active(ha);
                                  ddi_regs_map_free(&ha->db_dev_handle);
                          }
                          if (ha->iomap_dev_handle != ha->dev_handle) {
                                  ddi_regs_map_free(&ha->iomap_dev_handle);
*** 1924,1941 ****
  
                  ql_free_xioctl_resource(ha);
  
                  ql_destroy_mutex(ha);
  
!                 ql_free_phys(ha, &ha->hba_buf);
                  ql_free_phys(ha, &ha->fwexttracebuf);
                  ql_free_phys(ha, &ha->fwfcetracebuf);
  
                  ddi_regs_map_free(&ha->dev_handle);
                  if (ha->sbus_fpga_iobase != NULL) {
                          ddi_regs_map_free(&ha->sbus_fpga_dev_handle);
                  }
  
                  ql_fcache_rel(ha->fcache);
                  if (ha->vcache != NULL) {
                          kmem_free(ha->vcache, QL_24XX_VPD_SIZE);
                  }
--- 2185,2205 ----
  
                  ql_free_xioctl_resource(ha);
  
                  ql_destroy_mutex(ha);
  
!                 ql_delete_queues(ha);
                  ql_free_phys(ha, &ha->fwexttracebuf);
                  ql_free_phys(ha, &ha->fwfcetracebuf);
  
                  ddi_regs_map_free(&ha->dev_handle);
                  if (ha->sbus_fpga_iobase != NULL) {
                          ddi_regs_map_free(&ha->sbus_fpga_dev_handle);
                  }
+                 if (ha->mbar_dev_handle != NULL) {
+                         ddi_regs_map_free(&ha->mbar_dev_handle);
+                 }
  
                  ql_fcache_rel(ha->fcache);
                  if (ha->vcache != NULL) {
                          kmem_free(ha->vcache, QL_24XX_VPD_SIZE);
                  }
*** 1947,1957 ****
                  kmem_free(ha->adapter_stats, sizeof (*ha->adapter_stats));
  
                  kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
  
                  kmem_free(ha->outstanding_cmds,
!                     sizeof (*ha->outstanding_cmds) * MAX_OUTSTANDING_COMMANDS);
  
                  if (ha->n_port != NULL) {
                          kmem_free(ha->n_port, sizeof (ql_n_port_info_t));
                  }
  
--- 2211,2221 ----
                  kmem_free(ha->adapter_stats, sizeof (*ha->adapter_stats));
  
                  kmem_free(ha->ub_array, sizeof (*ha->ub_array) * QL_UB_LIMIT);
  
                  kmem_free(ha->outstanding_cmds,
!                     sizeof (*ha->outstanding_cmds) * ha->osc_max_cnt);
  
                  if (ha->n_port != NULL) {
                          kmem_free(ha->n_port, sizeof (ql_n_port_info_t));
                  }
  
*** 1959,1996 ****
                          kmem_free(ha->devpath, strlen(ha->devpath) + 1);
                  }
  
                  kmem_free(ha->dev, sizeof (*ha->dev) * DEVICE_HEAD_LIST_SIZE);
  
                  EL(ha, "detached\n");
  
                  ddi_soft_state_free(ql_state, (int)ha->instance);
  
                  break;
  
          case DDI_SUSPEND:
                  ADAPTER_STATE_LOCK(ha);
- 
-                 delay_cnt = 0;
                  ha->flags |= ADAPTER_SUSPENDED;
-                 while (ha->flags & ADAPTER_TIMER_BUSY && delay_cnt++ < 10) {
                          ADAPTER_STATE_UNLOCK(ha);
!                         delay(drv_usectohz(1000000));
!                         ADAPTER_STATE_LOCK(ha);
                  }
!                 if (ha->busy || ha->flags & ADAPTER_TIMER_BUSY) {
!                         ha->flags &= ~ADAPTER_SUSPENDED;
!                         ADAPTER_STATE_UNLOCK(ha);
!                         rval = DDI_FAILURE;
!                         cmn_err(CE_WARN, "!%s(%d): Fail suspend"
!                             " busy %xh flags %xh", QL_NAME, ha->instance,
!                             ha->busy, ha->flags);
!                         break;
                  }
  
-                 ADAPTER_STATE_UNLOCK(ha);
- 
                  if (ha->flags & IP_INITIALIZED) {
                          (void) ql_shutdown_ip(ha);
                  }
  
                  if ((suspend = ql_suspend_adapter(ha)) != QL_SUCCESS) {
--- 2223,2266 ----
                          kmem_free(ha->devpath, strlen(ha->devpath) + 1);
                  }
  
                  kmem_free(ha->dev, sizeof (*ha->dev) * DEVICE_HEAD_LIST_SIZE);
  
+                 (void) ql_plogi_params_desc_dtor(ha);
+ 
+                 (void) ql_nvram_cache_desc_dtor(ha);
+ 
+                 (void) qlc_fm_fini(ha);
+ 
                  EL(ha, "detached\n");
  
+                 (void) ql_el_trace_dealloc(ha);
+ 
                  ddi_soft_state_free(ql_state, (int)ha->instance);
  
+                 rval = DDI_SUCCESS;
+ 
                  break;
  
          case DDI_SUSPEND:
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags |= ADAPTER_SUSPENDED;
                  ADAPTER_STATE_UNLOCK(ha);
! 
!                 /* Disable driver timer if last adapter. */
!                 GLOBAL_TIMER_LOCK();
!                 if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
!                     ql_hba.last == &ha->hba) {
!                         timer_id = ql_timer_timeout_id;
!                         ql_timer_timeout_id = NULL;
                  }
!                 GLOBAL_TIMER_UNLOCK();
! 
!                 if (timer_id) {
!                         (void) untimeout(timer_id);
                  }
  
                  if (ha->flags & IP_INITIALIZED) {
                          (void) ql_shutdown_ip(ha);
                  }
  
                  if ((suspend = ql_suspend_adapter(ha)) != QL_SUCCESS) {
*** 2008,2032 ****
                          }
                          rval = DDI_FAILURE;
                          break;
                  }
  
-                 /* Acquire global state lock. */
-                 GLOBAL_STATE_LOCK();
- 
-                 /* Disable driver timer if last adapter. */
-                 if (ql_timer_timeout_id && ql_hba.first == &ha->hba &&
-                     ql_hba.last == &ha->hba) {
-                         timer_id = ql_timer_timeout_id;
-                         ql_timer_timeout_id = NULL;
-                 }
-                 GLOBAL_STATE_UNLOCK();
- 
-                 if (timer_id) {
-                         (void) untimeout(timer_id);
-                 }
- 
                  EL(ha, "suspended\n");
  
                  break;
  
          default:
--- 2278,2287 ----
*** 2035,2060 ****
          }
  
          kmem_free(buf, MAXPATHLEN);
  
          if (rval != DDI_SUCCESS) {
-                 if (ha != NULL) {
                          EL(ha, "failed, rval = %xh\n", rval);
                  } else {
                          /*EMPTY*/
!                         QL_PRINT_2(CE_CONT, "(%d): failed, rval = %xh\n",
!                             ddi_get_instance(dip), rval);
                  }
-         } else {
-                 /*EMPTY*/
-                 QL_PRINT_3(CE_CONT, "(%d): done\n", ddi_get_instance(dip));
-         }
  
          return (rval);
  }
  
- 
  /*
   * ql_power
   *      Power a device attached to the system.
   *
   * Input:
--- 2290,2308 ----
          }
  
          kmem_free(buf, MAXPATHLEN);
  
          if (rval != DDI_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
  /*
   * ql_power
   *      Power a device attached to the system.
   *
   * Input:
*** 2079,2094 ****
          char                    *buf;
          char                    *path;
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL || ha->pm_capable == 0) {
!                 QL_PRINT_2(CE_CONT, "(%d): no hba or PM not supported\n",
!                     ddi_get_instance(dip));
                  return (rval);
          }
  
!         QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
  
          buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
          path = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
  
          if (component != QL_POWER_COMPONENT || (level != PM_LEVEL_D0 &&
--- 2327,2341 ----
          char                    *buf;
          char                    *path;
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL || ha->pm_capable == 0) {
!                 QL_PRINT_2(ha, "no hba or PM not supported\n");
                  return (rval);
          }
  
!         QL_PRINT_10(ha, "started\n");
  
          buf = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
          path = (char *)(kmem_zalloc(MAXPATHLEN, KM_SLEEP));
  
          if (component != QL_POWER_COMPONENT || (level != PM_LEVEL_D0 &&
*** 2100,2110 ****
  
          GLOBAL_HW_LOCK();
          csr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR) + PCI_PMCSR;
          GLOBAL_HW_UNLOCK();
  
!         (void) snprintf(buf, sizeof (buf),
              "Qlogic %s(%d): %s\n\t", QL_NAME, ddi_get_instance(dip),
              ddi_pathname(dip, path));
  
          switch (level) {
          case PM_LEVEL_D0:       /* power up to D0 state - fully on */
--- 2347,2357 ----
  
          GLOBAL_HW_LOCK();
          csr = (uint8_t)ql_pci_config_get8(ha, PCI_CONF_CAP_PTR) + PCI_PMCSR;
          GLOBAL_HW_UNLOCK();
  
!         (void) snprintf(buf, MAXPATHLEN,
              "Qlogic %s(%d): %s\n\t", QL_NAME, ddi_get_instance(dip),
              ddi_pathname(dip, path));
  
          switch (level) {
          case PM_LEVEL_D0:       /* power up to D0 state - fully on */
*** 2170,2180 ****
  
          case PM_LEVEL_D3:       /* power down to D3 state - off */
  
                  QL_PM_LOCK(ha);
  
!                 if (ha->busy || ((ha->task_daemon_flags &
                      TASK_DAEMON_SLEEPING_FLG) == 0)) {
                          QL_PM_UNLOCK(ha);
                          break;
                  }
  
--- 2417,2427 ----
  
          case PM_LEVEL_D3:       /* power down to D3 state - off */
  
                  QL_PM_LOCK(ha);
  
!                 if (ha->pm_busy || ((ha->task_daemon_flags &
                      TASK_DAEMON_SLEEPING_FLG) == 0)) {
                          QL_PM_UNLOCK(ha);
                          break;
                  }
  
*** 2227,2237 ****
          }
  
          kmem_free(buf, MAXPATHLEN);
          kmem_free(path, MAXPATHLEN);
  
!         QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
  
          return (rval);
  }
  
  /*
--- 2474,2484 ----
          }
  
          kmem_free(buf, MAXPATHLEN);
          kmem_free(path, MAXPATHLEN);
  
!         QL_PRINT_10(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 2255,2276 ****
          uint32_t                stat;
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
                  /* Oh well.... */
!                 QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
                      ddi_get_instance(dip));
                  return (DDI_SUCCESS);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (CFG_IST(ha, CFG_CTRL_8021)) {
!                 (void) ql_stop_firmware(ha);
!         } else if (CFG_IST(ha, CFG_CTRL_242581)) {
                  WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
                  WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE);
                  WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
                  for (timer = 0; timer < 30000; timer++) {
                          stat = RD32_IO_REG(ha, risc2host);
                          if (stat & BIT_15) {
                                  if ((stat & 0xff) < 0x12) {
--- 2502,2563 ----
          uint32_t                stat;
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
                  /* Oh well.... */
!                 QL_PRINT_2(NULL, "no adapter, instance=%d\n",
                      ddi_get_instance(dip));
                  return (DDI_SUCCESS);
          }
  
!         QL_PRINT_3(ha, "started\n");
  
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                 ql_8021_clr_hw_intr(ha);
!                 ql_8021_clr_fw_intr(ha);
!                 WRT16_IO_REG(ha, mailbox_in[0], MBC_TOGGLE_INTERRUPT);
!                 WRT16_IO_REG(ha, mailbox_in[1], 0);
!                 WRT32_IO_REG(ha, nx_host_int, NX_MBX_CMD);
!                 for (timer = 0; timer < 20000; timer++) {
!                         stat = RD32_IO_REG(ha, risc2host);
!                         if (stat & BIT_15) {
!                                 ql_8021_clr_hw_intr(ha);
!                                 if ((stat & 0xff) < 0x12) {
!                                         ql_8021_clr_fw_intr(ha);
!                                         break;
!                                 }
!                                 ql_8021_clr_fw_intr(ha);
!                         }
!                         drv_usecwait(100);
!                 }
!                 ql_8021_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
!                 WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE);
!                 WRT16_IO_REG(ha, mailbox_in[1], 0);
!                 WRT32_IO_REG(ha, nx_host_int, NX_MBX_CMD);
!                 for (timer = 0; timer < 20000; timer++) {
!                         stat = RD32_IO_REG(ha, risc2host);
!                         if (stat & BIT_15) {
!                                 ql_8021_clr_hw_intr(ha);
!                                 if ((stat & 0xff) < 0x12) {
!                                         ql_8021_clr_fw_intr(ha);
!                                         break;
!                                 }
!                                 ql_8021_clr_fw_intr(ha);
!                         }
!                         drv_usecwait(100);
!                 }
!         } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                  WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
                  WRT16_IO_REG(ha, mailbox_in[0], MBC_STOP_FIRMWARE);
+                 WRT16_IO_REG(ha, mailbox_in[1], 0);
+                 WRT16_IO_REG(ha, mailbox_in[2], 0);
+                 WRT16_IO_REG(ha, mailbox_in[3], 0);
+                 WRT16_IO_REG(ha, mailbox_in[4], 0);
+                 WRT16_IO_REG(ha, mailbox_in[5], 0);
+                 WRT16_IO_REG(ha, mailbox_in[6], 0);
+                 WRT16_IO_REG(ha, mailbox_in[7], 0);
+                 WRT16_IO_REG(ha, mailbox_in[8], 0);
                  WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
                  for (timer = 0; timer < 30000; timer++) {
                          stat = RD32_IO_REG(ha, risc2host);
                          if (stat & BIT_15) {
                                  if ((stat & 0xff) < 0x12) {
*** 2281,2292 ****
--- 2568,2583 ----
                                  WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
                          }
                          drv_usecwait(100);
                  }
                  /* Reset the chip. */
+                 if (CFG_IST(ha, CFG_MWB_4096_SUPPORT)) {
                          WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN |
                              MWB_4096_BYTES);
+                 } else {
+                         WRT32_IO_REG(ha, ctrl_status, ISP_RESET | DMA_SHUTDOWN);
+                 }
                  drv_usecwait(100);
  
          } else {
                  /* Disable ISP interrupts. */
                  WRT16_IO_REG(ha, ictrl, 0);
*** 2298,2311 ****
                  WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
                  /* Release RISC module. */
                  WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
          }
  
!         ql_disable_intr(ha);
  
-         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
- 
          return (DDI_SUCCESS);
  }
  
  /* ************************************************************************ */
  /*              Fibre Channel Adapter (FCA) Transport Functions.            */
--- 2589,2600 ----
                  WRT16_IO_REG(ha, hccr, HC_RESET_RISC);
                  /* Release RISC module. */
                  WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (DDI_SUCCESS);
  }
  
  /* ************************************************************************ */
  /*              Fibre Channel Adapter (FCA) Transport Functions.            */
*** 2342,2387 ****
          uchar_t                 *port_pwwn = bind_info->port_pwwn.raw_wwn;
  
          /* get state info based on the dip */
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
                      ddi_get_instance(dip));
                  return (NULL);
          }
!         QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
  
          /* Verify port number is supported. */
          if (port_npiv != 0) {
                  if (!(ha->flags & VP_ENABLED)) {
!                         QL_PRINT_2(CE_CONT, "(%d): FC_NPIV_NOT_SUPPORTED\n",
!                             ha->instance);
                          port_info->pi_error = FC_NPIV_NOT_SUPPORTED;
                          return (NULL);
                  }
                  if (!(ha->flags & POINT_TO_POINT)) {
!                         QL_PRINT_2(CE_CONT, "(%d): FC_NPIV_WRONG_TOPOLOGY\n",
!                             ha->instance);
                          port_info->pi_error = FC_NPIV_WRONG_TOPOLOGY;
                          return (NULL);
                  }
                  if (!(ha->flags & FDISC_ENABLED)) {
!                         QL_PRINT_2(CE_CONT, "(%d): switch does not support "
!                             "FDISC\n", ha->instance);
                          port_info->pi_error = FC_NPIV_FDISC_FAILED;
                          return (NULL);
                  }
!                 if (bind_info->port_num > (CFG_IST(ha, CFG_CTRL_2422) ?
!                     MAX_24_VIRTUAL_PORTS : MAX_25_VIRTUAL_PORTS)) {
!                         QL_PRINT_2(CE_CONT, "(%d): port number=%d "
!                             "FC_OUTOFBOUNDS\n", ha->instance);
                          port_info->pi_error = FC_OUTOFBOUNDS;
                          return (NULL);
                  }
          } else if (bind_info->port_num != 0) {
!                 QL_PRINT_2(CE_CONT, "(%d): failed, port number=%d is not "
!                     "supported\n", ha->instance, bind_info->port_num);
                  port_info->pi_error = FC_OUTOFBOUNDS;
                  return (NULL);
          }
  
          /* Locate port context. */
--- 2631,2673 ----
          uchar_t                 *port_pwwn = bind_info->port_pwwn.raw_wwn;
  
          /* get state info based on the dip */
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(ha, "no adapter, instance=%d\n",
                      ddi_get_instance(dip));
                  return (NULL);
          }
!         QL_PRINT_10(ha, "started\n");
  
          /* Verify port number is supported. */
          if (port_npiv != 0) {
                  if (!(ha->flags & VP_ENABLED)) {
!                         QL_PRINT_2(ha, "FC_NPIV_NOT_SUPPORTED\n");
                          port_info->pi_error = FC_NPIV_NOT_SUPPORTED;
                          return (NULL);
                  }
                  if (!(ha->flags & POINT_TO_POINT)) {
!                         QL_PRINT_2(ha, "FC_NPIV_WRONG_TOPOLOGY\n");
                          port_info->pi_error = FC_NPIV_WRONG_TOPOLOGY;
                          return (NULL);
                  }
                  if (!(ha->flags & FDISC_ENABLED)) {
!                         QL_PRINT_2(ha, "switch does not support "
!                             "FDISC\n");
                          port_info->pi_error = FC_NPIV_FDISC_FAILED;
                          return (NULL);
                  }
!                 if (bind_info->port_num >= ha->max_vports) {
!                         QL_PRINT_2(ha, "port number=%d "
!                             "FC_OUTOFBOUNDS\n", bind_info->port_num);
                          port_info->pi_error = FC_OUTOFBOUNDS;
                          return (NULL);
                  }
          } else if (bind_info->port_num != 0) {
!                 QL_PRINT_2(ha, "failed, port number=%d is not "
!                     "supported\n", bind_info->port_num);
                  port_info->pi_error = FC_OUTOFBOUNDS;
                  return (NULL);
          }
  
          /* Locate port context. */
*** 2406,2417 ****
                          bcopy(port_pwwn,
                              vha->loginparams.nport_ww_name.raw_wwn, 8);
                  }
                  if (vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) {
                          if (ql_vport_enable(vha) != QL_SUCCESS) {
!                                 QL_PRINT_2(CE_CONT, "(%d): failed to enable "
!                                     "virtual port=%d\n", ha->instance,
                                      vha->vp_index);
                                  port_info->pi_error = FC_NPIV_FDISC_FAILED;
                                  return (NULL);
                          }
                          cmn_err(CE_CONT, "!Qlogic %s(%d) NPIV(%d) "
--- 2692,2703 ----
                          bcopy(port_pwwn,
                              vha->loginparams.nport_ww_name.raw_wwn, 8);
                  }
                  if (vha->vp_index != 0 && !(vha->flags & VP_ENABLED)) {
                          if (ql_vport_enable(vha) != QL_SUCCESS) {
!                                 QL_PRINT_2(ha, "failed to enable "
!                                     "virtual port=%d\n",
                                      vha->vp_index);
                                  port_info->pi_error = FC_NPIV_FDISC_FAILED;
                                  return (NULL);
                          }
                          cmn_err(CE_CONT, "!Qlogic %s(%d) NPIV(%d) "
*** 2426,2437 ****
                              port_nwwn[6], port_nwwn[7]);
                  }
  
                  /* stash the bind_info supplied by the FC Transport */
                  vha->bind_info.port_handle = bind_info->port_handle;
!                 vha->bind_info.port_statec_cb =
!                     bind_info->port_statec_cb;
                  vha->bind_info.port_unsol_cb = bind_info->port_unsol_cb;
  
                  /* Set port's source ID. */
                  port_info->pi_s_id.port_id = vha->d_id.b24;
  
--- 2712,2722 ----
                              port_nwwn[6], port_nwwn[7]);
                  }
  
                  /* stash the bind_info supplied by the FC Transport */
                  vha->bind_info.port_handle = bind_info->port_handle;
!                 vha->bind_info.port_statec_cb = bind_info->port_statec_cb;
                  vha->bind_info.port_unsol_cb = bind_info->port_unsol_cb;
  
                  /* Set port's source ID. */
                  port_info->pi_s_id.port_id = vha->d_id.b24;
  
*** 2442,2452 ****
  
                  /* Set port's hard address if enabled. */
                  port_info->pi_hard_addr.hard_addr = 0;
                  if (bind_info->port_num == 0) {
                          d_id.b24 = ha->d_id.b24;
!                         if (CFG_IST(ha, CFG_CTRL_24258081)) {
                                  if (ha->init_ctrl_blk.cb24.
                                      firmware_options_1[0] & BIT_0) {
                                          d_id.b.al_pa = ql_index_to_alpa[ha->
                                              init_ctrl_blk.cb24.
                                              hard_address[0]];
--- 2727,2737 ----
  
                  /* Set port's hard address if enabled. */
                  port_info->pi_hard_addr.hard_addr = 0;
                  if (bind_info->port_num == 0) {
                          d_id.b24 = ha->d_id.b24;
!                         if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                                  if (ha->init_ctrl_blk.cb24.
                                      firmware_options_1[0] & BIT_0) {
                                          d_id.b.al_pa = ql_index_to_alpa[ha->
                                              init_ctrl_blk.cb24.
                                              hard_address[0]];
*** 2494,2505 ****
                  ADAPTER_STATE_UNLOCK(ha);
                  /* Set port's current state. */
                  port_info->pi_port_state = vha->state;
          }
  
!         QL_PRINT_10(CE_CONT, "(%d,%d): done, pi_port_state=%xh, "
!             "pi_s_id.port_id=%xh\n", ha->instance, ha->vp_index,
              port_info->pi_port_state, port_info->pi_s_id.port_id);
  
          return (fca_handle);
  }
  
--- 2779,2790 ----
                  ADAPTER_STATE_UNLOCK(ha);
                  /* Set port's current state. */
                  port_info->pi_port_state = vha->state;
          }
  
!         QL_PRINT_10(ha, "done, pi_port_state=%xh, "
!             "pi_s_id.port_id=%xh\n",
              port_info->pi_port_state, port_info->pi_s_id.port_id);
  
          return (fca_handle);
  }
  
*** 2521,2560 ****
          uint32_t                flgs;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
                  /*EMPTY*/
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
          } else {
!                 QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance,
!                     ha->vp_index);
  
                  if (!(ha->flags & FCA_BOUND)) {
                          /*EMPTY*/
!                         QL_PRINT_2(CE_CONT, "(%d): port=%d already unbound\n",
!                             ha->instance, ha->vp_index);
                  } else {
                          if (ha->vp_index != 0 && ha->flags & VP_ENABLED) {
                                  if ((tq = ql_loop_id_to_queue(ha,
                                      FL_PORT_24XX_HDL)) != NULL) {
                                          (void) ql_logout_fabric_port(ha, tq);
                                  }
-                                 (void) ql_vport_control(ha, (uint8_t)
-                                     (CFG_IST(ha, CFG_CTRL_2425) ?
-                                     VPC_DISABLE_INIT : VPC_DISABLE_LOGOUT));
                                  flgs = FCA_BOUND | VP_ENABLED;
                          } else {
                                  flgs = FCA_BOUND;
                          }
                          ADAPTER_STATE_LOCK(ha);
                          ha->flags &= ~flgs;
                          ADAPTER_STATE_UNLOCK(ha);
                  }
  
!                 QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
!                     ha->vp_index);
          }
  }
  
  /*
   * ql_init_pkt
--- 2806,2842 ----
          uint32_t                flgs;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
                  /*EMPTY*/
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
          } else {
!                 QL_PRINT_10(ha, "started\n");
  
                  if (!(ha->flags & FCA_BOUND)) {
                          /*EMPTY*/
!                         QL_PRINT_2(ha, "port already unbound\n");
                  } else {
                          if (ha->vp_index != 0 && ha->flags & VP_ENABLED) {
+                                 (void) ql_vport_control(ha, (uint8_t)
+                                     (CFG_IST(ha, CFG_FC_TYPE) ?
+                                     VPC_DISABLE_INIT : VPC_DISABLE_LOGOUT));
                                  if ((tq = ql_loop_id_to_queue(ha,
                                      FL_PORT_24XX_HDL)) != NULL) {
                                          (void) ql_logout_fabric_port(ha, tq);
                                  }
                                  flgs = FCA_BOUND | VP_ENABLED;
                          } else {
                                  flgs = FCA_BOUND;
                          }
                          ADAPTER_STATE_LOCK(ha);
                          ha->flags &= ~flgs;
                          ADAPTER_STATE_UNLOCK(ha);
                  }
  
!                 QL_PRINT_10(ha, "done\n");
          }
  }
  
  /*
   * ql_init_pkt
*** 2581,2598 ****
          ql_srb_t                *sp;
          int                     rval = FC_SUCCESS;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          sp = (ql_srb_t *)pkt->pkt_fca_private;
          sp->flags = 0;
  
          /* init cmd links */
          sp->cmd.base_address = sp;
          sp->cmd.prev = NULL;
          sp->cmd.next = NULL;
--- 2863,2881 ----
          ql_srb_t                *sp;
          int                     rval = FC_SUCCESS;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started\n");
  
          sp = (ql_srb_t *)pkt->pkt_fca_private;
          sp->flags = 0;
+         sp->handle = 0;
  
          /* init cmd links */
          sp->cmd.base_address = sp;
          sp->cmd.prev = NULL;
          sp->cmd.next = NULL;
*** 2606,2628 ****
          sp->pkt = pkt;
          sp->ha = ha;
          sp->magic_number = QL_FCA_BRAND;
          sp->sg_dma.dma_handle = NULL;
  #ifndef __sparc
!         if (CFG_IST(ha, CFG_CTRL_8021)) {
                  /* Setup DMA for scatter gather list. */
                  sp->sg_dma.size = sizeof (cmd6_2400_dma_t);
                  sp->sg_dma.type = LITTLE_ENDIAN_DMA;
!                 sp->sg_dma.cookie_count = 1;
                  sp->sg_dma.alignment = 64;
                  if (ql_alloc_phys(ha, &sp->sg_dma, KM_SLEEP) != QL_SUCCESS) {
                          rval = FC_NOMEM;
                  }
          }
  #endif  /* __sparc */
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 2889,2911 ----
          sp->pkt = pkt;
          sp->ha = ha;
          sp->magic_number = QL_FCA_BRAND;
          sp->sg_dma.dma_handle = NULL;
  #ifndef __sparc
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
                  /* Setup DMA for scatter gather list. */
                  sp->sg_dma.size = sizeof (cmd6_2400_dma_t);
                  sp->sg_dma.type = LITTLE_ENDIAN_DMA;
!                 sp->sg_dma.max_cookie_count = 1;
                  sp->sg_dma.alignment = 64;
                  if (ql_alloc_phys(ha, &sp->sg_dma, KM_SLEEP) != QL_SUCCESS) {
                          rval = FC_NOMEM;
                  }
          }
  #endif  /* __sparc */
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 2649,2663 ****
          int rval;
          ql_srb_t *sp;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          sp = (ql_srb_t *)pkt->pkt_fca_private;
  
          if (sp->magic_number != QL_FCA_BRAND) {
                  EL(ha, "failed, FC_BADPACKET\n");
--- 2932,2946 ----
          int rval;
          ql_srb_t *sp;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started\n");
  
          sp = (ql_srb_t *)pkt->pkt_fca_private;
  
          if (sp->magic_number != QL_FCA_BRAND) {
                  EL(ha, "failed, FC_BADPACKET\n");
*** 2666,2676 ****
                  sp->magic_number = NULL;
                  ql_free_phys(ha, &sp->sg_dma);
                  rval = FC_SUCCESS;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 2949,2959 ----
                  sp->magic_number = NULL;
                  ql_free_phys(ha, &sp->sg_dma);
                  rval = FC_SUCCESS;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 2703,2721 ****
          ql_srb_t                *sp = (ql_srb_t *)pkt->pkt_fca_private;
  
          /* Verify proper command. */
          ha = ql_cmd_setup(fca_handle, pkt, &rval);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
                      rval, fca_handle);
                  return (FC_INVALID_REQUEST);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Wait for suspension to end. */
          TASK_DAEMON_LOCK(ha);
!         while (ha->task_daemon_flags & QL_SUSPENDED) {
                  ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
  
                  /* 30 seconds from now */
                  if (cv_reltimedwait(&ha->pha->cv_dr_suspended,
                      &ha->pha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
--- 2986,3004 ----
          ql_srb_t                *sp = (ql_srb_t *)pkt->pkt_fca_private;
  
          /* Verify proper command. */
          ha = ql_cmd_setup(fca_handle, pkt, &rval);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
                      rval, fca_handle);
                  return (FC_INVALID_REQUEST);
          }
!         QL_PRINT_3(ha, "started\n");
  
          /* Wait for suspension to end. */
          TASK_DAEMON_LOCK(ha);
!         while (DRIVER_SUSPENDED(ha)) {
                  ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
  
                  /* 30 seconds from now */
                  if (cv_reltimedwait(&ha->pha->cv_dr_suspended,
                      &ha->pha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
*** 2761,2785 ****
  
          /* map the type of ELS to a function */
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
              (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
  
! #if 0
!         QL_PRINT_3(CE_CONT, "(%d): command fhdr:\n", ha->instance);
!         QL_DUMP_3((uint8_t *)&pkt->pkt_cmd_fhdr, 32,
!             sizeof (fc_frame_hdr_t) / 4);
!         QL_PRINT_3(CE_CONT, "(%d): command:\n", ha->instance);
!         QL_DUMP_3((uint8_t *)&els, 32, sizeof (els) / 4);
! #endif
  
          sp->iocb = ha->els_cmd;
          sp->req_cnt = 1;
  
          switch (els.ls_code) {
          case LA_ELS_RJT:
          case LA_ELS_ACC:
-                 EL(ha, "LA_ELS_RJT\n");
                  pkt->pkt_state = FC_PKT_SUCCESS;
                  rval = FC_SUCCESS;
                  break;
          case LA_ELS_PLOGI:
          case LA_ELS_PDISC:
--- 3044,3062 ----
  
          /* map the type of ELS to a function */
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
              (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_10(ha, "els.ls_code=%xh, d_id=%xh\n", els.ls_code,
!             pkt->pkt_cmd_fhdr.d_id);
  
          sp->iocb = ha->els_cmd;
          sp->req_cnt = 1;
  
          switch (els.ls_code) {
          case LA_ELS_RJT:
          case LA_ELS_ACC:
                  pkt->pkt_state = FC_PKT_SUCCESS;
                  rval = FC_SUCCESS;
                  break;
          case LA_ELS_PLOGI:
          case LA_ELS_PDISC:
*** 2843,2874 ****
                  pkt->pkt_reason = FC_REASON_UNSUPPORTED;
                  rval = FC_SUCCESS;
                  break;
          }
  
- #if 0
-         QL_PRINT_3(CE_CONT, "(%d): response fhdr:\n", ha->instance);
-         QL_DUMP_3((uint8_t *)&pkt->pkt_resp_fhdr, 32,
-             sizeof (fc_frame_hdr_t) / 4);
- #endif
          /*
           * Return success if the srb was consumed by an iocb. The packet
           * completion callback will be invoked by the response handler.
           */
          if (rval == QL_CONSUMED) {
                  rval = FC_SUCCESS;
          } else if (rval == FC_SUCCESS &&
              !(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
                  /* Do command callback only if no error */
!                 ql_awaken_task_daemon(ha, sp, 0, 0);
          }
  
          if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 3120,3147 ----
                  pkt->pkt_reason = FC_REASON_UNSUPPORTED;
                  rval = FC_SUCCESS;
                  break;
          }
  
          /*
           * Return success if the srb was consumed by an iocb. The packet
           * completion callback will be invoked by the response handler.
           */
          if (rval == QL_CONSUMED) {
                  rval = FC_SUCCESS;
          } else if (rval == FC_SUCCESS &&
              !(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
                  /* Do command callback only if no error */
!                 ql_io_comp(sp);
          }
  
          if (rval != FC_SUCCESS) {
!                 EL(ha, "rval=%x, ls_code=%xh sent to d_id=%xh, sp=%ph\n",
!                     rval, els.ls_code, pkt->pkt_cmd_fhdr.d_id, sp);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_10(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 2896,2910 ****
          int                     rval;
          uint32_t                *rptr = (uint32_t *)ptr;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (strcmp(cap, FC_NODE_WWN) == 0) {
                  bcopy((void *)&ha->loginparams.node_ww_name.raw_wwn[0],
                      ptr, 8);
                  rval = FC_CAP_FOUND;
--- 3169,3183 ----
          int                     rval;
          uint32_t                *rptr = (uint32_t *)ptr;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started\n");
  
          if (strcmp(cap, FC_NODE_WWN) == 0) {
                  bcopy((void *)&ha->loginparams.node_ww_name.raw_wwn[0],
                      ptr, 8);
                  rval = FC_CAP_FOUND;
*** 2921,2932 ****
  #ifdef __sparc
                  /*
                   * Disable streaming for certain 2 chip adapters
                   * below Psycho to handle Psycho byte hole issue.
                   */
!                 if ((CFG_IST(ha, CFG_MULTI_CHIP_ADAPTER)) &&
!                     (!CFG_IST(ha, CFG_SBUS_CARD))) {
                          for (psydip = ddi_get_parent(ha->dip); psydip;
                              psydip = ddi_get_parent(psydip)) {
                                  if (strcmp(ddi_driver_name(psydip),
                                      "pcipsy") == 0) {
                                          break;
--- 3194,3205 ----
  #ifdef __sparc
                  /*
                   * Disable streaming for certain 2 chip adapters
                   * below Psycho to handle Psycho byte hole issue.
                   */
!                 if (ha->flags & MULTI_CHIP_ADAPTER &&
!                     !CFG_IST(ha, CFG_SBUS_CARD)) {
                          for (psydip = ddi_get_parent(ha->dip); psydip;
                              psydip = ddi_get_parent(psydip)) {
                                  if (strcmp(ddi_driver_name(psydip),
                                      "pcipsy") == 0) {
                                          break;
*** 2942,2960 ****
                          *rptr = (uint32_t)FC_ALLOW_STREAMING;
                          EL(ha, "Allow Streaming\n");
                  }
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
!                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
!                         *rptr = (uint32_t)CHAR_TO_SHORT(
!                             ha->init_ctrl_blk.cb24.max_frame_length[0],
!                             ha->init_ctrl_blk.cb24.max_frame_length[1]);
!                 } else {
!                         *rptr = (uint32_t)CHAR_TO_SHORT(
!                             ha->init_ctrl_blk.cb.max_frame_length[0],
!                             ha->init_ctrl_blk.cb.max_frame_length[1]);
!                 }
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
                  *rptr = FC_RESET_RETURN_ALL;
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
--- 3215,3225 ----
                          *rptr = (uint32_t)FC_ALLOW_STREAMING;
                          EL(ha, "Allow Streaming\n");
                  }
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_CAP_PAYLOAD_SIZE) == 0) {
!                 *rptr = ha->loginparams.common_service.rx_bufsize;
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_CAP_POST_RESET_BEHAVIOR) == 0) {
                  *rptr = FC_RESET_RETURN_ALL;
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_CAP_FCP_DMA) == 0) {
*** 2963,2973 ****
          } else {
                  EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
                  rval = FC_CAP_ERROR;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 3228,3238 ----
          } else {
                  EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
                  rval = FC_CAP_ERROR;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 2995,3009 ****
          ql_adapter_state_t      *ha;
          int                     rval;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (strcmp(cap, FC_NODE_WWN) == 0) {
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
                  rval = FC_CAP_FOUND;
--- 3260,3274 ----
          ql_adapter_state_t      *ha;
          int                     rval;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started\n");
  
          if (strcmp(cap, FC_NODE_WWN) == 0) {
                  rval = FC_CAP_FOUND;
          } else if (strcmp(cap, FC_LOGIN_PARAMS) == 0) {
                  rval = FC_CAP_FOUND;
*** 3016,3026 ****
          } else {
                  EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
                  rval = FC_CAP_ERROR;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 3281,3291 ----
          } else {
                  EL(ha, "unknown=%s, FC_CAP_ERROR\n", cap);
                  rval = FC_CAP_ERROR;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 3048,3069 ****
          clock_t                 timer = drv_usectohz(30000000);
          int                     rval = FC_SUCCESS;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          mapbuf->lilp_magic = (uint16_t)MAGIC_LIRP;
          mapbuf->lilp_myalpa = ha->d_id.b.al_pa;
  
          /* Wait for suspension to end. */
          TASK_DAEMON_LOCK(ha);
!         while (ha->task_daemon_flags & QL_SUSPENDED) {
                  ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
  
                  /* 30 seconds from now */
                  if (cv_reltimedwait(&ha->pha->cv_dr_suspended,
                      &ha->pha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
--- 3313,3334 ----
          clock_t                 timer = drv_usectohz(30000000);
          int                     rval = FC_SUCCESS;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started\n");
  
          mapbuf->lilp_magic = (uint16_t)MAGIC_LIRP;
          mapbuf->lilp_myalpa = ha->d_id.b.al_pa;
  
          /* Wait for suspension to end. */
          TASK_DAEMON_LOCK(ha);
!         while (DRIVER_SUSPENDED(ha)) {
                  ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
  
                  /* 30 seconds from now */
                  if (cv_reltimedwait(&ha->pha->cv_dr_suspended,
                      &ha->pha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
*** 3090,3111 ****
                   * offline condition, let's wait for few seconds
                   * for any loop transitions before we reset the.
                   * chip and restart all over again.
                   */
                  ql_delay(ha, 2000000);
!                 EL(ha, "failed, FC_NOMAP\n");
!                 rval = FC_NOMAP;
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): my_alpa %xh len %xh "
!                     "data %xh %xh %xh %xh\n", ha->instance,
                      mapbuf->lilp_myalpa, mapbuf->lilp_length,
                      mapbuf->lilp_alpalist[0], mapbuf->lilp_alpalist[1],
                      mapbuf->lilp_alpalist[2], mapbuf->lilp_alpalist[3]);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  #if 0
          QL_DUMP_3((uint8_t *)mapbuf, 8, sizeof (fc_lilpmap_t));
  #endif
          return (rval);
  }
--- 3355,3376 ----
                   * offline condition, let's wait for few seconds
                   * for any loop transitions before we reset the.
                   * chip and restart all over again.
                   */
                  ql_delay(ha, 2000000);
!                 EL(ha, "failed, FC_NO_MAP\n");
!                 rval = FC_NO_MAP;
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "my_alpa %xh len %xh "
!                     "data %xh %xh %xh %xh\n",
                      mapbuf->lilp_myalpa, mapbuf->lilp_length,
                      mapbuf->lilp_alpalist[0], mapbuf->lilp_alpalist[1],
                      mapbuf->lilp_alpalist[2], mapbuf->lilp_alpalist[3]);
          }
  
!         QL_PRINT_3(ha, "done\n");
  #if 0
          QL_DUMP_3((uint8_t *)mapbuf, 8, sizeof (fc_lilpmap_t));
  #endif
          return (rval);
  }
*** 3136,3160 ****
          ql_srb_t                *sp = (ql_srb_t *)pkt->pkt_fca_private;
  
          /* Verify proper command. */
          ha = ql_cmd_setup(fca_handle, pkt, &rval);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
                      rval, fca_handle);
                  return (rval);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started command:\n", ha->instance);
! #if 0
!         QL_DUMP_3((uint8_t *)&pkt->pkt_cmd_fhdr, 32,
!             sizeof (fc_frame_hdr_t) / 4);
!         QL_PRINT_3(CE_CONT, "(%d): command:\n", ha->instance);
!         QL_DUMP_3((uint8_t *)pkt->pkt_cmd, 8, pkt->pkt_cmdlen);
! #endif
  
          /* Reset SRB flags. */
          sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED | SRB_RETRY |
!             SRB_POLL | SRB_WATCHDOG_ENABLED | SRB_ABORT | SRB_UB_CALLBACK |
              SRB_UB_RSCN | SRB_UB_FCP | SRB_FCP_CMD_PKT | SRB_FCP_DATA_PKT |
              SRB_FCP_RSP_PKT | SRB_IP_PKT | SRB_GENERIC_SERVICES_PKT |
              SRB_COMMAND_TIMEOUT | SRB_ABORTING | SRB_IN_DEVICE_QUEUE |
              SRB_IN_TOKEN_ARRAY | SRB_UB_FREE_REQUESTED | SRB_UB_ACQUIRED |
              SRB_MS_PKT | SRB_ELS_PKT);
--- 3401,3419 ----
          ql_srb_t                *sp = (ql_srb_t *)pkt->pkt_fca_private;
  
          /* Verify proper command. */
          ha = ql_cmd_setup(fca_handle, pkt, &rval);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, ql_cmd_setup=%xh, fcah=%ph\n",
                      rval, fca_handle);
                  return (rval);
          }
!         QL_PRINT_3(ha, "started, d_id=%xh\n", pkt->pkt_cmd_fhdr.d_id);
  
          /* Reset SRB flags. */
          sp->flags &= ~(SRB_ISP_STARTED | SRB_ISP_COMPLETED | SRB_RETRY |
!             SRB_POLL | SRB_WATCHDOG_ENABLED | SRB_UB_CALLBACK |
              SRB_UB_RSCN | SRB_UB_FCP | SRB_FCP_CMD_PKT | SRB_FCP_DATA_PKT |
              SRB_FCP_RSP_PKT | SRB_IP_PKT | SRB_GENERIC_SERVICES_PKT |
              SRB_COMMAND_TIMEOUT | SRB_ABORTING | SRB_IN_DEVICE_QUEUE |
              SRB_IN_TOKEN_ARRAY | SRB_UB_FREE_REQUESTED | SRB_UB_ACQUIRED |
              SRB_MS_PKT | SRB_ELS_PKT);
*** 3168,3177 ****
--- 3427,3440 ----
          switch (pkt->pkt_cmd_fhdr.r_ctl) {
          case R_CTL_COMMAND:
                  if (pkt->pkt_cmd_fhdr.type == FC_TYPE_SCSI_FCP) {
                          sp->flags |= SRB_FCP_CMD_PKT;
                          rval = ql_fcp_scsi_cmd(ha, pkt, sp);
+                 } else {
+                         pkt->pkt_state = FC_PKT_LOCAL_RJT;
+                         pkt->pkt_reason = FC_REASON_UNSUPPORTED;
+                         rval = FC_TRANSPORT_ERROR;
                  }
                  break;
  
          default:
                  /* Setup response header and buffer. */
*** 3180,3198 ****
--- 3443,3475 ----
                  }
  
                  switch (pkt->pkt_cmd_fhdr.r_ctl) {
                  case R_CTL_UNSOL_DATA:
                          if (pkt->pkt_cmd_fhdr.type == FC_TYPE_IS8802_SNAP) {
+                                 if (CFG_IST(ha, CFG_FCIP_SUPPORT) &&
+                                     ha->vp_index == 0) {
                                          sp->flags |= SRB_IP_PKT;
                                          rval = ql_fcp_ip_cmd(ha, pkt, sp);
+                                 } else {
+                                         cmn_err(CE_NOTE, "%s(%d) FC-IP is not "
+                                             "supported on this adapter\n",
+                                             QL_NAME, ha->instance);
+                                         pkt->pkt_state = FC_PKT_LOCAL_RJT;
+                                         pkt->pkt_reason = FC_REASON_UNSUPPORTED;
+                                         rval = FC_TRANSPORT_ERROR;
                                  }
+                         }
                          break;
  
                  case R_CTL_UNSOL_CONTROL:
                          if (pkt->pkt_cmd_fhdr.type == FC_TYPE_FC_SERVICES) {
                                  sp->flags |= SRB_GENERIC_SERVICES_PKT;
                                  rval = ql_fc_services(ha, pkt);
+                         } else {
+                                 pkt->pkt_state = FC_PKT_LOCAL_RJT;
+                                 pkt->pkt_reason = FC_REASON_UNSUPPORTED;
+                                 rval = FC_TRANSPORT_ERROR;
                          }
                          break;
  
                  case R_CTL_SOLICITED_DATA:
                  case R_CTL_STATUS:
*** 3208,3218 ****
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  
          return (rval);
  }
  
--- 3485,3495 ----
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 3253,3281 ****
          int                     ub_updated = FALSE;
  
          /* Check handle. */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d,%d): started, count = %xh\n",
!             ha->instance, ha->vp_index, *count);
  
          QL_PM_LOCK(ha);
          if (ha->power_level != PM_LEVEL_D0) {
                  QL_PM_UNLOCK(ha);
!                 QL_PRINT_3(CE_CONT, "(%d,%d): down done\n", ha->instance,
!                     ha->vp_index);
                  return (FC_FAILURE);
          }
          QL_PM_UNLOCK(ha);
  
-         /* Acquire adapter state lock. */
-         ADAPTER_STATE_LOCK(ha);
- 
          /* Check the count. */
          if ((*count + ha->ub_allocated) > QL_UB_LIMIT) {
                  *count = 0;
                  EL(ha, "failed, FC_TOOMANY\n");
                  rval = FC_TOOMANY;
--- 3530,3553 ----
          int                     ub_updated = FALSE;
  
          /* Check handle. */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started, count = %xh\n", *count);
  
          QL_PM_LOCK(ha);
          if (ha->power_level != PM_LEVEL_D0) {
                  QL_PM_UNLOCK(ha);
!                 QL_PRINT_3(ha, "down done\n");
                  return (FC_FAILURE);
          }
          QL_PM_UNLOCK(ha);
  
          /* Check the count. */
          if ((*count + ha->ub_allocated) > QL_UB_LIMIT) {
                  *count = 0;
                  EL(ha, "failed, FC_TOOMANY\n");
                  rval = FC_TOOMANY;
*** 3387,3410 ****
                          ub_updated = TRUE;
                          QL_UB_UNLOCK(ha);
                  }
          }
  
-         /* Release adapter state lock. */
-         ADAPTER_STATE_UNLOCK(ha);
- 
          /* IP buffer. */
          if (ub_updated) {
!                 if ((type == FC_TYPE_IS8802_SNAP) &&
!                     (!(CFG_IST(ha, (CFG_CTRL_6322 | CFG_CTRL_2581))))) {
  
                          ADAPTER_STATE_LOCK(ha);
                          ha->flags |= IP_ENABLED;
                          ADAPTER_STATE_UNLOCK(ha);
  
                          if (!(ha->flags & IP_INITIALIZED)) {
!                                 if (CFG_IST(ha, CFG_CTRL_2422)) {
                                          ha->ip_init_ctrl_blk.cb24.mtu_size[0] =
                                              LSB(ql_ip_mtu);
                                          ha->ip_init_ctrl_blk.cb24.mtu_size[1] =
                                              MSB(ql_ip_mtu);
                                          ha->ip_init_ctrl_blk.cb24.buf_size[0] =
--- 3659,3680 ----
                          ub_updated = TRUE;
                          QL_UB_UNLOCK(ha);
                  }
          }
  
          /* IP buffer. */
          if (ub_updated) {
!                 if (type == FC_TYPE_IS8802_SNAP &&
!                     CFG_IST(ha, CFG_FCIP_SUPPORT) &&
!                     ha->vp_index == 0) {
  
                          ADAPTER_STATE_LOCK(ha);
                          ha->flags |= IP_ENABLED;
                          ADAPTER_STATE_UNLOCK(ha);
  
                          if (!(ha->flags & IP_INITIALIZED)) {
!                                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                                          ha->ip_init_ctrl_blk.cb24.mtu_size[0] =
                                              LSB(ql_ip_mtu);
                                          ha->ip_init_ctrl_blk.cb24.mtu_size[1] =
                                              MSB(ql_ip_mtu);
                                          ha->ip_init_ctrl_blk.cb24.buf_size[0] =
*** 3452,3463 ****
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d,%d): done\n", ha->instance,
!                     ha->vp_index);
          }
          return (rval);
  }
  
  /*
--- 3722,3732 ----
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 3488,3506 ****
          int                     rval = FC_SUCCESS;
  
          /* Check handle. */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
-         /* Acquire adapter state lock. */
-         ADAPTER_STATE_LOCK(ha);
- 
          /* Check all returned tokens. */
          for (index = 0; index < count; index++) {
                  fc_unsol_buf_t  *ubp;
  
                  /* Check the token range. */
--- 3757,3772 ----
          int                     rval = FC_SUCCESS;
  
          /* Check handle. */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started\n");
  
          /* Check all returned tokens. */
          for (index = 0; index < count; index++) {
                  fc_unsol_buf_t  *ubp;
  
                  /* Check the token range. */
*** 3526,3538 ****
                  sp->flags |= SRB_UB_FREE_REQUESTED;
  
                  while (!(sp->flags & SRB_UB_IN_FCA) ||
                      (sp->flags & (SRB_UB_CALLBACK | SRB_UB_ACQUIRED))) {
                          QL_UB_UNLOCK(ha);
-                         ADAPTER_STATE_UNLOCK(ha);
                          delay(drv_usectohz(100000));
-                         ADAPTER_STATE_LOCK(ha);
                          QL_UB_LOCK(ha);
                  }
                  ha->ub_array[ub_array_index] = NULL;
                  QL_UB_UNLOCK(ha);
                  ql_free_unsolicited_buffer(ha, ubp);
--- 3792,3802 ----
*** 3542,3563 ****
                  /*
                   * Signal any pending hardware reset when there are
                   * no more unsolicited buffers in use.
                   */
                  if (ha->ub_allocated == 0) {
                          cv_broadcast(&ha->pha->cv_ub);
                  }
          }
  
-         /* Release adapter state lock. */
-         ADAPTER_STATE_UNLOCK(ha);
- 
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 3806,3826 ----
                  /*
                   * Signal any pending hardware reset when there are
                   * no more unsolicited buffers in use.
                   */
                  if (ha->ub_allocated == 0) {
+                         QL_UB_LOCK(ha);
                          cv_broadcast(&ha->pha->cv_ub);
+                         QL_UB_UNLOCK(ha);
                  }
          }
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 3590,3607 ****
          int                     ub_ip_updated = FALSE;
  
          /* Check handle. */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, ": failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Acquire adapter state lock. */
-         ADAPTER_STATE_LOCK(ha);
          QL_UB_LOCK(ha);
  
          /* Check all returned tokens. */
          for (index = 0; index < count; index++) {
                  /* Check the token range. */
--- 3853,3869 ----
          int                     ub_ip_updated = FALSE;
  
          /* Check handle. */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, ": failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
!         QL_PRINT_3(ha, "started\n");
  
          /* Acquire adapter state lock. */
          QL_UB_LOCK(ha);
  
          /* Check all returned tokens. */
          for (index = 0; index < count; index++) {
                  /* Check the token range. */
*** 3647,3658 ****
                          }
                  }
          }
  
          QL_UB_UNLOCK(ha);
-         /* Release adapter state lock. */
-         ADAPTER_STATE_UNLOCK(ha);
  
          /*
           * XXX: We should call ql_isp_rcvbuf() to return a
           * buffer to ISP only if the number of buffers fall below
           * the low water mark.
--- 3909,3918 ----
*** 3663,3673 ****
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 3923,3933 ----
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 3690,3744 ****
   *      FC_UNBOUND - the fca_handle specified is not bound.
   *
   * Context:
   *      Kernel context.
   */
  static int
  ql_abort(opaque_t fca_handle, fc_packet_t *pkt, int flags)
  {
          port_id_t               d_id;
          ql_link_t               *link;
          ql_adapter_state_t      *ha, *pha;
-         ql_srb_t                *sp;
          ql_tgt_t                *tq;
          ql_lun_t                *lq;
          int                     rval = FC_ABORTED;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
  
          pha = ha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
  
          /* Get target queue pointer. */
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          tq = ql_d_id_to_queue(ha, d_id);
  
!         if ((tq == NULL) || (pha->task_daemon_flags & LOOP_DOWN)) {
!                 if (tq == NULL) {
                          EL(ha, "failed, FC_TRANSPORT_ERROR\n");
                          rval = FC_TRANSPORT_ERROR;
                  } else {
                          EL(ha, "failed, FC_OFFLINE\n");
                          rval = FC_OFFLINE;
                  }
                  return (rval);
          }
  
-         sp = (ql_srb_t *)pkt->pkt_fca_private;
-         lq = sp->lun_queue;
- 
-         /* Set poll flag if sleep wanted. */
-         if (flags == KM_SLEEP) {
-                 sp->flags |= SRB_POLL;
-         }
- 
          /* Acquire target queue lock. */
          DEVICE_QUEUE_LOCK(tq);
          REQUEST_RING_LOCK(ha);
  
          /* If command not already started. */
--- 3950,3998 ----
   *      FC_UNBOUND - the fca_handle specified is not bound.
   *
   * Context:
   *      Kernel context.
   */
+ /*ARGSUSED*/
  static int
  ql_abort(opaque_t fca_handle, fc_packet_t *pkt, int flags)
  {
          port_id_t               d_id;
          ql_link_t               *link;
          ql_adapter_state_t      *ha, *pha;
          ql_tgt_t                *tq;
          ql_lun_t                *lq;
          int                     rval = FC_ABORTED;
+         ql_srb_t                *sp = (ql_srb_t *)pkt->pkt_fca_private;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
  
          pha = ha->pha;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Get target queue pointer. */
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          tq = ql_d_id_to_queue(ha, d_id);
  
!         if ((tq == NULL) || (lq = sp->lun_queue) == NULL ||
!             (pha->task_daemon_flags & LOOP_DOWN)) {
!                 if (tq == NULL || lq == NULL) {
                          EL(ha, "failed, FC_TRANSPORT_ERROR\n");
                          rval = FC_TRANSPORT_ERROR;
                  } else {
                          EL(ha, "failed, FC_OFFLINE\n");
                          rval = FC_OFFLINE;
                  }
                  return (rval);
          }
  
          /* Acquire target queue lock. */
          DEVICE_QUEUE_LOCK(tq);
          REQUEST_RING_LOCK(ha);
  
          /* If command not already started. */
*** 3781,3791 ****
  
                          /* Set return status */
                          pkt->pkt_reason = CS_ABORTED;
  
                          sp->cmd.next = NULL;
!                         ql_done(&sp->cmd);
                          rval = FC_ABORTED;
                  } else {
                          EL(ha, "failed, FC_BADEXCHANGE\n");
                          rval = FC_BADEXCHANGE;
                  }
--- 4035,4045 ----
  
                          /* Set return status */
                          pkt->pkt_reason = CS_ABORTED;
  
                          sp->cmd.next = NULL;
!                         ql_done(&sp->cmd, B_TRUE);
                          rval = FC_ABORTED;
                  } else {
                          EL(ha, "failed, FC_BADEXCHANGE\n");
                          rval = FC_BADEXCHANGE;
                  }
*** 3807,3841 ****
                   */
                  REQUEST_RING_UNLOCK(ha);
                  DEVICE_QUEUE_UNLOCK(tq);
                  rval = FC_ABORTED;
          } else {
!                 request_t       *ep = pha->request_ring_bp;
!                 uint16_t        cnt;
  
                  if (sp->handle != 0) {
!                         for (cnt = 0; cnt < REQUEST_ENTRY_CNT; cnt++) {
!                                 if (sp->handle == ddi_get32(
!                                     pha->hba_buf.acc_handle, &ep->handle)) {
!                                         ep->entry_type = INVALID_ENTRY_TYPE;
!                                         break;
                                  }
!                                 ep++;
                          }
                  }
! 
                  /* Release device queue lock. */
!                 REQUEST_RING_UNLOCK(ha);
!                 DEVICE_QUEUE_UNLOCK(tq);
  
-                 sp->flags |= SRB_ABORTING;
                  (void) ql_abort_command(ha, sp);
                  pkt->pkt_reason = CS_ABORTED;
                  rval = FC_ABORTED;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d,%d): done\n", ha->instance, ha->vp_index);
  
          return (rval);
  }
  
  /*
--- 4061,4138 ----
                   */
                  REQUEST_RING_UNLOCK(ha);
                  DEVICE_QUEUE_UNLOCK(tq);
                  rval = FC_ABORTED;
          } else {
!                 ql_request_q_t  *req_q;
!                 request_t       *pio;
!                 uint32_t        index;
  
+                 REQUEST_RING_UNLOCK(ha);
+                 DEVICE_QUEUE_UNLOCK(tq);
+ 
+                 INTR_LOCK(ha);
+                 sp->flags |= SRB_ABORTING;
                  if (sp->handle != 0) {
!                         index = sp->handle & OSC_INDEX_MASK;
!                         if (ha->outstanding_cmds[index] == sp) {
!                                 ha->outstanding_cmds[index] =
!                                     QL_ABORTED_SRB(ha);
                          }
!                         if (ha->req_q[1] != NULL && sp->rsp_q_number != 0) {
!                                 req_q = ha->req_q[1];
!                         } else {
!                                 req_q = ha->req_q[0];
                          }
+                         pio = sp->request_ring_ptr;
+                         if (sp->handle ==
+                             ddi_get32(req_q->req_ring.acc_handle,
+                             &pio->handle)) {
+                                 EL(ha, "inflight sp=%ph, handle=%xh, "
+                                     "invalidated\n", (void *)sp, sp->handle);
+                                 for (index = 0; index < sp->req_cnt; index++) {
+                                         ddi_put8(req_q->req_ring.acc_handle,
+                                             &pio->entry_type,
+                                             ABORTED_ENTRY_TYPE);
+                                         pio++;
+                                         if (pio == (request_t *)
+                                             ((uintptr_t)req_q->req_ring.bp +
+                                             req_q->req_ring.size)) {
+                                                 pio = req_q->req_ring.bp;
                                          }
!                                 }
!                         }
!                         /* Decrement outstanding commands on device. */
!                         if (tq->outcnt != 0) {
!                                 tq->outcnt--;
!                         }
!                         if (sp->flags & SRB_FCP_CMD_PKT &&
!                             lq->lun_outcnt != 0) {
!                                 lq->lun_outcnt--;
!                         }
!                         /* Remove command from watchdog queue. */
!                         if (sp->flags & SRB_WATCHDOG_ENABLED) {
!                                 ql_remove_link(&tq->wdg, &sp->wdg);
!                                 sp->flags &= ~SRB_WATCHDOG_ENABLED;
!                         }
                          /* Release device queue lock. */
!                         INTR_UNLOCK(ha);
  
                          (void) ql_abort_command(ha, sp);
+                         sp->handle = 0;
+                 } else {
+                         /* Release device queue lock. */
+                         INTR_UNLOCK(ha);
+                 }
+ 
+                 sp->flags &= ~SRB_IN_TOKEN_ARRAY;
+                 sp->flags |= SRB_ISP_COMPLETED;
                  pkt->pkt_reason = CS_ABORTED;
                  rval = FC_ABORTED;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 3860,3877 ****
          ql_adapter_state_t      *ha;
          int                     rval = FC_SUCCESS, rval2;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d,%d): started, cmd=%d\n", ha->instance,
!             ha->vp_index, cmd);
  
          switch (cmd) {
          case FC_FCA_CORE:
                  /* dump firmware core if specified. */
                  if (ha->vp_index == 0) {
                          if (ql_dump_firmware(ha) != QL_SUCCESS) {
--- 4157,4180 ----
          ql_adapter_state_t      *ha;
          int                     rval = FC_SUCCESS, rval2;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
  
!         QL_PRINT_3(ha, "started, cmd=%d\n", cmd);
  
+         if (ha->task_daemon_flags & (ABORT_ISP_ACTIVE | LOOP_RESYNC_ACTIVE |
+             DRIVER_STALL | ISP_ABORT_NEEDED | LOOP_RESYNC_NEEDED)) {
+                 EL(ha, "driver stalled, FC_TRAN_BUSY, dtf=%xh\n",
+                     ha->task_daemon_flags);
+                 return (FC_TRAN_BUSY);
+         }
+ 
          switch (cmd) {
          case FC_FCA_CORE:
                  /* dump firmware core if specified. */
                  if (ha->vp_index == 0) {
                          if (ql_dump_firmware(ha) != QL_SUCCESS) {
*** 3958,3969 ****
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "cmd=%xh, failed=%xh\n", cmd, rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d,%d): done\n", ha->instance,
!                     ha->vp_index);
          }
  
          return (rval);
  }
  
--- 4261,4271 ----
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "cmd=%xh, failed=%xh\n", cmd, rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 4003,4035 ****
          int                     i0;
          uint8_t                 *bptr;
          int                     rval2, rval = FC_SUCCESS;
          uint32_t                opcode;
          uint32_t                set_flags = 0;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, ": failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
          pha = ha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started=%xh\n", ha->instance,
!             cmd->pm_cmd_code);
  
!         ql_awaken_task_daemon(ha, NULL, DRIVER_STALL, 0);
! 
!         /*
!          * Wait for all outstanding commands to complete
!          */
!         index = (uint16_t)ql_wait_outstanding(ha);
! 
!         if (index != MAX_OUTSTANDING_COMMANDS) {
!                 ql_awaken_task_daemon(ha, NULL, 0, DRIVER_STALL);
!                 ql_restart_queues(ha);
!                 EL(ha, "failed, FC_TRAN_BUSY\n");
                  return (FC_TRAN_BUSY);
          }
  
          switch (cmd->pm_cmd_code) {
          case FC_PORT_BYPASS:
--- 4305,4334 ----
          int                     i0;
          uint8_t                 *bptr;
          int                     rval2, rval = FC_SUCCESS;
          uint32_t                opcode;
          uint32_t                set_flags = 0;
+         fc_fca_p2p_info_t       *p2p_info;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, ": failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (FC_UNBOUND);
          }
          pha = ha->pha;
  
! #ifdef  QL_DEBUG_LEVEL_10
!         if (cmd->pm_cmd_code != FC_PORT_GET_FW_REV) {
!                 QL_PRINT_10(ha, "started=%xh\n", cmd->pm_cmd_code);
!         }
! #endif
  
!         if (ha->task_daemon_flags & (ABORT_ISP_ACTIVE | LOOP_RESYNC_ACTIVE |
!             DRIVER_STALL | ISP_ABORT_NEEDED | LOOP_RESYNC_NEEDED)) {
!                 EL(ha, "driver stalled, FC_TRAN_BUSY, dtf=%xh\n",
!                     ha->task_daemon_flags);
                  return (FC_TRAN_BUSY);
          }
  
          switch (cmd->pm_cmd_code) {
          case FC_PORT_BYPASS:
*** 4115,4184 ****
                          rval = FC_FAILURE;
                  }
                  QL_DUMP_UNLOCK(pha);
                  break;
          case FC_PORT_FORCE_DUMP:
-                 PORTMANAGE_LOCK(ha);
                  if (ql_dump_firmware(ha) != QL_SUCCESS) {
                          EL(ha, "failed, FC_PORT_FORCE_DUMP FC_FAILURE\n");
                          rval = FC_FAILURE;
                  }
-                 PORTMANAGE_UNLOCK(ha);
                  break;
-         case FC_PORT_DOWNLOAD_FW:
-                 PORTMANAGE_LOCK(ha);
-                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
-                         if (ql_24xx_load_flash(ha, (uint8_t *)cmd->pm_data_buf,
-                             (uint32_t)cmd->pm_data_len,
-                             ha->flash_fw_addr << 2) != QL_SUCCESS) {
-                                 EL(ha, "failed, FC_PORT_DOWNLOAD_FW\n");
-                                 rval = FC_FAILURE;
-                         }
-                         ql_reset_chip(ha);
-                         set_flags |= ISP_ABORT_NEEDED;
-                 } else {
-                         /* Save copy of the firmware. */
-                         if (pha->risc_code != NULL) {
-                                 kmem_free(pha->risc_code, pha->risc_code_size);
-                                 pha->risc_code = NULL;
-                                 pha->risc_code_size = 0;
-                         }
- 
-                         pha->risc_code = kmem_alloc(cmd->pm_data_len,
-                             KM_SLEEP);
-                         if (pha->risc_code != NULL) {
-                                 pha->risc_code_size =
-                                     (uint32_t)cmd->pm_data_len;
-                                 bcopy(cmd->pm_data_buf, pha->risc_code,
-                                     cmd->pm_data_len);
- 
-                                 /* Do abort to force reload. */
-                                 ql_reset_chip(ha);
-                                 if (ql_abort_isp(ha) != QL_SUCCESS) {
-                                         kmem_free(pha->risc_code,
-                                             pha->risc_code_size);
-                                         pha->risc_code = NULL;
-                                         pha->risc_code_size = 0;
-                                         ql_reset_chip(ha);
-                                         (void) ql_abort_isp(ha);
-                                         EL(ha, "failed, FC_PORT_DOWNLOAD_FW"
-                                             " FC_FAILURE\n");
-                                         rval = FC_FAILURE;
-                                 }
-                         }
-                 }
-                 PORTMANAGE_UNLOCK(ha);
-                 break;
          case FC_PORT_GET_DUMP_SIZE:
                  bp = (uint32_t *)cmd->pm_data_buf;
                  *bp = pha->risc_dump_size;
                  break;
          case FC_PORT_DIAG:
!                 /*
!                  * Prevents concurrent diags
!                  */
!                 PORTMANAGE_LOCK(ha);
  
                  /* Wait for suspension to end. */
                  for (timer = 0; timer < 3000 &&
                      pha->task_daemon_flags & QL_LOOP_TRANSITION; timer++) {
                          ql_delay(ha, 10000);
--- 4414,4434 ----
                          rval = FC_FAILURE;
                  }
                  QL_DUMP_UNLOCK(pha);
                  break;
          case FC_PORT_FORCE_DUMP:
                  if (ql_dump_firmware(ha) != QL_SUCCESS) {
                          EL(ha, "failed, FC_PORT_FORCE_DUMP FC_FAILURE\n");
                          rval = FC_FAILURE;
                  }
                  break;
          case FC_PORT_GET_DUMP_SIZE:
                  bp = (uint32_t *)cmd->pm_data_buf;
                  *bp = pha->risc_dump_size;
                  break;
          case FC_PORT_DIAG:
!                 EL(ha, "diag cmd=%xh\n", cmd->pm_cmd_flags);
  
                  /* Wait for suspension to end. */
                  for (timer = 0; timer < 3000 &&
                      pha->task_daemon_flags & QL_LOOP_TRANSITION; timer++) {
                          ql_delay(ha, 10000);
*** 4185,4207 ****
                  }
  
                  if (pha->task_daemon_flags & QL_LOOP_TRANSITION) {
                          EL(ha, "failed, FC_TRAN_BUSY-2\n");
                          rval = FC_TRAN_BUSY;
-                         PORTMANAGE_UNLOCK(ha);
                          break;
                  }
  
                  switch (cmd->pm_cmd_flags) {
                  case QL_DIAG_EXEFMW:
                          if (ql_start_firmware(ha) != QL_SUCCESS) {
                                  EL(ha, "failed, QL_DIAG_EXEFMW FC_FAILURE\n");
                                  rval = FC_FAILURE;
                          }
                          break;
                  case QL_DIAG_CHKCMDQUE:
!                         for (i0 = 1, cnt = 0; i0 < MAX_OUTSTANDING_COMMANDS;
                              i0++) {
                                  cnt += (pha->outstanding_cmds[i0] != NULL);
                          }
                          if (cnt != 0) {
                                  EL(ha, "failed, QL_DIAG_CHKCMDQUE "
--- 4435,4464 ----
                  }
  
                  if (pha->task_daemon_flags & QL_LOOP_TRANSITION) {
                          EL(ha, "failed, FC_TRAN_BUSY-2\n");
                          rval = FC_TRAN_BUSY;
                          break;
                  }
  
+                 if ((rval2 = ql_stall_driver(ha, 0)) != QL_SUCCESS) {
+                         EL(ha, "stall_driver status=%xh, FC_TRAN_BUSY\n",
+                             rval2);
+                         ql_restart_driver(ha);
+                         rval = FC_TRAN_BUSY;
+                         break;
+                 }
+ 
                  switch (cmd->pm_cmd_flags) {
                  case QL_DIAG_EXEFMW:
                          if (ql_start_firmware(ha) != QL_SUCCESS) {
                                  EL(ha, "failed, QL_DIAG_EXEFMW FC_FAILURE\n");
                                  rval = FC_FAILURE;
                          }
                          break;
                  case QL_DIAG_CHKCMDQUE:
!                         for (i0 = 1, cnt = 0; i0 < pha->osc_max_cnt;
                              i0++) {
                                  cnt += (pha->outstanding_cmds[i0] != NULL);
                          }
                          if (cnt != 0) {
                                  EL(ha, "failed, QL_DIAG_CHKCMDQUE "
*** 4252,4262 ****
                          }
                          /*
                           * Don't do the wrap test on a 2200 when the
                           * firmware is running.
                           */
!                         if (!CFG_IST(ha, CFG_CTRL_2200)) {
                                  mcp = (app_mbx_cmd_t *)cmd->pm_data_buf;
                                  mr.mb[1] = mcp->mb[1];
                                  mr.mb[2] = mcp->mb[2];
                                  mr.mb[3] = mcp->mb[3];
                                  mr.mb[4] = mcp->mb[4];
--- 4509,4519 ----
                          }
                          /*
                           * Don't do the wrap test on a 2200 when the
                           * firmware is running.
                           */
!                         if (!CFG_IST(ha, CFG_CTRL_22XX)) {
                                  mcp = (app_mbx_cmd_t *)cmd->pm_data_buf;
                                  mr.mb[1] = mcp->mb[1];
                                  mr.mb[2] = mcp->mb[2];
                                  mr.mb[3] = mcp->mb[3];
                                  mr.mb[4] = mcp->mb[4];
*** 4330,4340 ****
                              (uint8_t *)cmd->pm_data_buf,
                              (uint8_t *)buffer_xmt.bp,
                              cmd->pm_data_len, DDI_DEV_AUTOINCR);
  
                          /* 22xx's adapter must be in loop mode for test. */
!                         if (CFG_IST(ha, CFG_CTRL_2200)) {
                                  bptr = &ha->init_ctrl_blk.cb.add_fw_opt[0];
                                  if (ha->flags & POINT_TO_POINT ||
                                      (ha->task_daemon_flags & LOOP_DOWN &&
                                      *bptr & (BIT_6 | BIT_5 | BIT_4))) {
                                          cnt = *bptr;
--- 4587,4597 ----
                              (uint8_t *)cmd->pm_data_buf,
                              (uint8_t *)buffer_xmt.bp,
                              cmd->pm_data_len, DDI_DEV_AUTOINCR);
  
                          /* 22xx's adapter must be in loop mode for test. */
!                         if (CFG_IST(ha, CFG_CTRL_22XX)) {
                                  bptr = &ha->init_ctrl_blk.cb.add_fw_opt[0];
                                  if (ha->flags & POINT_TO_POINT ||
                                      (ha->task_daemon_flags & LOOP_DOWN &&
                                      *bptr & (BIT_6 | BIT_5 | BIT_4))) {
                                          cnt = *bptr;
*** 4358,4367 ****
--- 4615,4628 ----
                          lb->transfer_data_address =
                              buffer_xmt.cookie.dmac_address;
                          lb->receive_data_address =
                              buffer_rcv.cookie.dmac_address;
  
+                         if (CFG_IST(ha, CFG_LOOP_POINT_SUPPORT)) {
+                                 (void) ql_set_loop_point(ha, lb->options);
+                         }
+ 
                          if (ql_loop_back(ha, 0, lb,
                              buffer_xmt.cookie.dmac_notused,
                              buffer_rcv.cookie.dmac_notused) == QL_SUCCESS) {
                                  bzero((void *)cmd->pm_stat_buf,
                                      cmd->pm_stat_len);
*** 4373,4382 ****
--- 4634,4647 ----
                          } else {
                                  EL(ha, "failed, QL_DIAG_LPBDTA FC_FAILURE\n");
                                  rval = FC_FAILURE;
                          }
  
+                         if (CFG_IST(ha, CFG_LOOP_POINT_SUPPORT)) {
+                                 (void) ql_set_loop_point(ha, 0);
+                         }
+ 
                          ql_free_phys(ha, &buffer_xmt);
                          ql_free_phys(ha, &buffer_rcv);
  
                          /* Needed to recover the f/w */
                          set_flags |= ISP_ABORT_NEEDED;
*** 4442,4452 ****
                           * while we are at it lets ask for
                           * real echo (bit 15)
                           */
                          echo.options = BIT_15;
                          if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING) &&
!                             !(CFG_IST(ha, CFG_CTRL_8081))) {
                                  echo.options = (uint16_t)
                                      (echo.options | BIT_6);
                          }
  
                          /*
--- 4707,4717 ----
                           * while we are at it lets ask for
                           * real echo (bit 15)
                           */
                          echo.options = BIT_15;
                          if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING) &&
!                             !(CFG_IST(ha, CFG_FCOE_SUPPORT))) {
                                  echo.options = (uint16_t)
                                      (echo.options | BIT_6);
                          }
  
                          /*
*** 4531,4541 ****
                          EL(ha, "unknown=%xh, FC_PORT_DIAG "
                              "FC_INVALID_REQUEST\n", cmd->pm_cmd_flags);
                          rval = FC_INVALID_REQUEST;
                          break;
                  }
!                 PORTMANAGE_UNLOCK(ha);
                  break;
          case FC_PORT_LINK_STATE:
                  /* Check for name equal to null. */
                  for (index = 0; index < 8 && index < cmd->pm_cmd_len;
                      index++) {
--- 4796,4806 ----
                          EL(ha, "unknown=%xh, FC_PORT_DIAG "
                              "FC_INVALID_REQUEST\n", cmd->pm_cmd_flags);
                          rval = FC_INVALID_REQUEST;
                          break;
                  }
!                 ql_restart_driver(ha);
                  break;
          case FC_PORT_LINK_STATE:
                  /* Check for name equal to null. */
                  for (index = 0; index < 8 && index < cmd->pm_cmd_len;
                      index++) {
*** 4576,4585 ****
--- 4841,4857 ----
                          cmd->pm_stat_buf[0] = (int8_t)LSB(ha->state);
                          cmd->pm_stat_buf[1] = (int8_t)MSB(ha->state);
                  }
                  break;
          case FC_PORT_INITIALIZE:
+                 if ((rval2 = ql_stall_driver(ha, 0)) != QL_SUCCESS) {
+                         EL(ha, "stall_driver status=%xh, FC_TRAN_BUSY\n",
+                             rval2);
+                         ql_restart_driver(ha);
+                         rval = FC_TRAN_BUSY;
+                         break;
+                 }
                  if (cmd->pm_cmd_len >= 8) {
                          tq = NULL;
                          for (index = 0; index < DEVICE_HEAD_LIST_SIZE &&
                              tq == NULL; index++) {
                                  for (link = ha->dev[index].first; link != NULL;
*** 4609,4618 ****
--- 4881,4891 ----
                          EL(ha, "failed, FC_PORT_INITIALIZE FC_FAILURE-2, "
                              "clen=%lxh\n", cmd->pm_cmd_len);
  
                          rval = FC_FAILURE;
                  }
+                 ql_restart_driver(ha);
                  break;
          case FC_PORT_RLS:
                  if (cmd->pm_data_len < sizeof (fc_rls_acc_t)) {
                          EL(ha, "failed, buffer size passed: %lxh, "
                              "req: %lxh\n", cmd->pm_data_len,
*** 4631,4640 ****
--- 4904,4915 ----
  
                          rls = (fc_rls_acc_t *)cmd->pm_data_buf;
                          LITTLE_ENDIAN_32(&rls->rls_link_fail);
                          LITTLE_ENDIAN_32(&rls->rls_sync_loss);
                          LITTLE_ENDIAN_32(&rls->rls_sig_loss);
+                         LITTLE_ENDIAN_32(&rls->rls_prim_seq_err);
+                         LITTLE_ENDIAN_32(&rls->rls_invalid_word);
                          LITTLE_ENDIAN_32(&rls->rls_invalid_crc);
  #endif /* _BIG_ENDIAN */
                  }
                  break;
          case FC_PORT_GET_NODE_ID:
*** 4650,4661 ****
                          EL(ha, "failed, FC_PORT_SET_NODE_ID FC_FAILURE\n");
                          rval = FC_FAILURE;
                  }
                  break;
          case FC_PORT_DOWNLOAD_FCODE:
!                 PORTMANAGE_LOCK(ha);
!                 if ((CFG_IST(ha, CFG_CTRL_24258081)) == 0) {
                          rval = ql_load_flash(ha, (uint8_t *)cmd->pm_data_buf,
                              (uint32_t)cmd->pm_data_len);
                  } else {
                          if (cmd->pm_data_buf[0] == 4 &&
                              cmd->pm_data_buf[8] == 0 &&
--- 4925,4942 ----
                          EL(ha, "failed, FC_PORT_SET_NODE_ID FC_FAILURE\n");
                          rval = FC_FAILURE;
                  }
                  break;
          case FC_PORT_DOWNLOAD_FCODE:
!                 if ((rval2 = ql_stall_driver(ha, 0)) != QL_SUCCESS) {
!                         EL(ha, "stall_driver status=%xh, FC_TRAN_BUSY\n",
!                             rval2);
!                         ql_restart_driver(ha);
!                         rval = FC_TRAN_BUSY;
!                         break;
!                 }
!                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_1)) {
                          rval = ql_load_flash(ha, (uint8_t *)cmd->pm_data_buf,
                              (uint32_t)cmd->pm_data_len);
                  } else {
                          if (cmd->pm_data_buf[0] == 4 &&
                              cmd->pm_data_buf[8] == 0 &&
*** 4679,4690 ****
                  } else {
                          rval = FC_SUCCESS;
                  }
                  ql_reset_chip(ha);
                  set_flags |= ISP_ABORT_NEEDED;
!                 PORTMANAGE_UNLOCK(ha);
                  break;
          default:
                  EL(ha, "unknown=%xh, FC_BADCMD\n", cmd->pm_cmd_code);
                  rval = FC_BADCMD;
                  break;
          }
--- 4960,5018 ----
                  } else {
                          rval = FC_SUCCESS;
                  }
                  ql_reset_chip(ha);
                  set_flags |= ISP_ABORT_NEEDED;
!                 ql_restart_driver(ha);
                  break;
+ 
+         case FC_PORT_GET_P2P_INFO:
+ 
+                 bzero(cmd->pm_data_buf, cmd->pm_data_len);
+                 if (cmd->pm_data_len < sizeof (fc_fca_p2p_info_t)) {
+                         EL(ha, "inadequate data length")
+                         rval = FC_NOMEM;
+                         break;
+                 }
+ 
+                 p2p_info = (fc_fca_p2p_info_t *)cmd->pm_data_buf;
+ 
+                 if ((ha->topology & QL_N_PORT) &&
+                     (ha->flags & POINT_TO_POINT)) {
+                         p2p_info->fca_d_id = ha->d_id.b24;
+                         p2p_info->d_id = ha->n_port->d_id.b24;
+ 
+                         bcopy((void *) &ha->n_port->port_name[0],
+                             (caddr_t)&p2p_info->pwwn, 8);
+                         bcopy((void *) &ha->n_port->node_name[0],
+                             (caddr_t)&p2p_info->nwwn, 8);
+                         rval = FC_SUCCESS;
+ 
+                         EL(ha, "P2P HID=%xh, d_id=%xh, WWPN=%02x%02x%02x%02x"
+                             "%02x%02x%02x%02x : "
+                             "WWNN=%02x%02x%02x%02x%02x%02x%02x%02x\n",
+                             p2p_info->fca_d_id, p2p_info->d_id,
+                             ha->n_port->port_name[0],
+                             ha->n_port->port_name[1], ha->n_port->port_name[2],
+                             ha->n_port->port_name[3], ha->n_port->port_name[4],
+                             ha->n_port->port_name[5], ha->n_port->port_name[6],
+                             ha->n_port->port_name[7], ha->n_port->node_name[0],
+                             ha->n_port->node_name[1], ha->n_port->node_name[2],
+                             ha->n_port->node_name[3], ha->n_port->node_name[4],
+                             ha->n_port->node_name[5], ha->n_port->node_name[6],
+                             ha->n_port->node_name[7]);
+                         break;
+                 } else {
+                         EL(ha, "No p2p info reported in non n2n topology\n");
+                         rval = FC_BADCMD;
+                 }
+                 break;
+ 
+         case FC_PORT_DOWNLOAD_FW:
+                 EL(ha, "unsupported=%xh, FC_BADCMD\n", cmd->pm_cmd_code);
+                 rval = FC_BADCMD;
+                 break;
          default:
                  EL(ha, "unknown=%xh, FC_BADCMD\n", cmd->pm_cmd_code);
                  rval = FC_BADCMD;
                  break;
          }
*** 4696,4712 ****
          while (timer++ < 3000 &&
              ha->task_daemon_flags & (QL_LOOP_TRANSITION | DRIVER_STALL)) {
                  ql_delay(ha, 10000);
          }
  
-         ql_restart_queues(ha);
- 
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  
          return (rval);
  }
  
--- 5024,5038 ----
          while (timer++ < 3000 &&
              ha->task_daemon_flags & (QL_LOOP_TRANSITION | DRIVER_STALL)) {
                  ql_delay(ha, 10000);
          }
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 4720,4742 ****
          id.r.rsvd_1 = 0;
          id.b24 = d_id.port_id;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (NULL);
          }
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance, id.b24);
  
          tq = ql_d_id_to_queue(ha, id);
  
!         if (tq == NULL) {
!                 EL(ha, "failed, tq=NULL\n");
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (tq);
  }
  
  /* ************************************************************************ */
--- 5046,5068 ----
          id.r.rsvd_1 = 0;
          id.b24 = d_id.port_id;
  
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (NULL);
          }
!         QL_PRINT_3(ha, "started, d_id=%xh\n", id.b24);
  
          tq = ql_d_id_to_queue(ha, id);
  
!         if (tq == NULL && id.b24 != 0 && id.b24 != FS_BROADCAST) {
!                 EL(ha, "failed, no tq available for d_id: %xh\n", id.b24);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (tq);
  }
  
  /* ************************************************************************ */
*** 4771,4787 ****
  
          /* check that the handle is assigned by this FCA */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
                  *rval = FC_UNBOUND;
!                 QL_PRINT_2(CE_CONT, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (NULL);
          }
          pha = ha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (ddi_in_panic() || pkt->pkt_tran_flags & FC_TRAN_DUMPING) {
                  return (ha);
          }
  
--- 5097,5113 ----
  
          /* check that the handle is assigned by this FCA */
          ha = ql_fca_handle_to_state(fca_handle);
          if (ha == NULL) {
                  *rval = FC_UNBOUND;
!                 QL_PRINT_2(NULL, "failed, no adapter=%ph\n",
                      (void *)fca_handle);
                  return (NULL);
          }
          pha = ha->pha;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (ddi_in_panic() || pkt->pkt_tran_flags & FC_TRAN_DUMPING) {
                  return (ha);
          }
  
*** 4827,4876 ****
                          }
                          DEVICE_QUEUE_UNLOCK(tq);
                  }
          }
  
          /*
           * Check DMA pointers.
           */
          *rval = DDI_SUCCESS;
          if (pkt->pkt_cmd_acc != NULL && pkt->pkt_cmdlen) {
                  QL_CLEAR_DMA_HANDLE(pkt->pkt_cmd_dma);
!                 *rval = ddi_check_dma_handle(pkt->pkt_cmd_dma);
!                 if (*rval == DDI_SUCCESS) {
!                         *rval = ddi_check_acc_handle(pkt->pkt_cmd_acc);
                  }
          }
  
          if (pkt->pkt_resp_acc != NULL && *rval == DDI_SUCCESS &&
              pkt->pkt_rsplen != 0) {
                  QL_CLEAR_DMA_HANDLE(pkt->pkt_resp_dma);
!                 *rval = ddi_check_dma_handle(pkt->pkt_resp_dma);
!                 if (*rval == DDI_SUCCESS) {
!                         *rval = ddi_check_acc_handle(pkt->pkt_resp_acc);
                  }
          }
  
          /*
           * Minimum branch conditional; Change it with care.
           */
          if (((pkt->pkt_data_acc != NULL) & (*rval == DDI_SUCCESS) &
              (pkt->pkt_datalen != 0)) != 0) {
                  QL_CLEAR_DMA_HANDLE(pkt->pkt_data_dma);
!                 *rval = ddi_check_dma_handle(pkt->pkt_data_dma);
!                 if (*rval == DDI_SUCCESS) {
!                         *rval = ddi_check_acc_handle(pkt->pkt_data_acc);
                  }
          }
  
!         if (*rval != DDI_SUCCESS) {
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_DMA_ERROR;
  
                  /* Do command callback. */
                  if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
!                         ql_awaken_task_daemon(ha, sp, 0, 0);
                  }
                  *rval = FC_BADPACKET;
                  EL(ha, "failed, bad DMA pointers\n");
                  return (NULL);
          }
--- 5153,5230 ----
                          }
                          DEVICE_QUEUE_UNLOCK(tq);
                  }
          }
  
+         /* Check for packet already running. */
+         if (sp->handle != 0) {
+                 *rval = FC_DEVICE_BUSY;
+                 cmn_err(CE_WARN, "%s(%d) already running pkt=%p, sp=%p, "
+                     "sp->pkt=%p, sp->hdl=%x, spf=%x, cq=%p\n", QL_NAME,
+                     ha->instance, (void *)pkt, (void *)sp, (void *)sp->pkt,
+                     sp->handle, sp->flags, (void *)sp->cmd.head);
+                 return (NULL);
+         }
+         if (ha->rsp_queues_cnt > 1) {
+                 ADAPTER_STATE_LOCK(ha);
+                 sp->rsp_q_number = ha->rsp_q_number++;
+                 if (ha->rsp_q_number == ha->rsp_queues_cnt) {
+                         ha->rsp_q_number = 0;
+                 }
+                 ADAPTER_STATE_UNLOCK(ha);
+         } else {
+                 sp->rsp_q_number = 0;
+         }
+ 
          /*
           * Check DMA pointers.
           */
          *rval = DDI_SUCCESS;
          if (pkt->pkt_cmd_acc != NULL && pkt->pkt_cmdlen) {
                  QL_CLEAR_DMA_HANDLE(pkt->pkt_cmd_dma);
! 
!                 *rval = qlc_fm_check_dma_handle(ha, pkt->pkt_cmd_dma);
!                 if (*rval == DDI_FM_OK) {
!                         *rval = qlc_fm_check_acc_handle(ha,
!                             pkt->pkt_cmd_acc);
                  }
          }
  
          if (pkt->pkt_resp_acc != NULL && *rval == DDI_SUCCESS &&
              pkt->pkt_rsplen != 0) {
                  QL_CLEAR_DMA_HANDLE(pkt->pkt_resp_dma);
! 
!                 *rval = qlc_fm_check_dma_handle(ha, pkt->pkt_resp_dma);
!                 if (*rval == DDI_FM_OK) {
!                         *rval = qlc_fm_check_acc_handle(ha,
!                             pkt->pkt_resp_acc);
                  }
          }
  
          /*
           * Minimum branch conditional; Change it with care.
           */
          if (((pkt->pkt_data_acc != NULL) & (*rval == DDI_SUCCESS) &
              (pkt->pkt_datalen != 0)) != 0) {
                  QL_CLEAR_DMA_HANDLE(pkt->pkt_data_dma);
! 
!                 *rval = qlc_fm_check_dma_handle(ha, pkt->pkt_data_dma);
!                 if (*rval == DDI_FM_OK) {
!                         *rval = qlc_fm_check_acc_handle(ha,
!                             pkt->pkt_data_acc);
                  }
          }
  
!         if (*rval != DDI_FM_OK) {
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_DMA_ERROR;
+                 pkt->pkt_expln = FC_EXPLN_NONE;
+                 pkt->pkt_action = FC_ACTION_RETRYABLE;
  
                  /* Do command callback. */
                  if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
!                         ql_io_comp(sp);
                  }
                  *rval = FC_BADPACKET;
                  EL(ha, "failed, bad DMA pointers\n");
                  return (NULL);
          }
*** 4880,4890 ****
                  EL(ha, "failed, magic number=%xh\n", sp->magic_number);
                  return (NULL);
          }
          *rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (ha);
  }
  
  /*
--- 5234,5244 ----
                  EL(ha, "failed, magic number=%xh\n", sp->magic_number);
                  return (NULL);
          }
          *rval = FC_SUCCESS;
  
!         QL_PRINT_3(ha, "done\n");
  
          return (ha);
  }
  
  /*
*** 4910,4936 ****
          la_els_logi_t           acc;
          class_svc_param_t       *class3_param;
          int                     ret;
          int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             pkt->pkt_cmd_fhdr.d_id);
  
          TASK_DAEMON_LOCK(ha);
          if (!(ha->task_daemon_flags & STATE_ONLINE)) {
                  TASK_DAEMON_UNLOCK(ha);
!                 QL_PRINT_3(CE_CONT, "(%d): offline done\n", ha->instance);
                  return (FC_OFFLINE);
          }
          TASK_DAEMON_UNLOCK(ha);
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          ret = QL_SUCCESS;
  
!         if (CFG_IST(ha, CFG_CTRL_2425) && ha->topology & QL_N_PORT) {
                  /*
                   * In p2p topology it sends a PLOGI after determining
                   * it has the N_Port login initiative.
                   */
                  ret = ql_p2p_plogi(ha, pkt);
--- 5264,5289 ----
          la_els_logi_t           acc;
          class_svc_param_t       *class3_param;
          int                     ret;
          int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", pkt->pkt_cmd_fhdr.d_id);
  
          TASK_DAEMON_LOCK(ha);
          if (!(ha->task_daemon_flags & STATE_ONLINE)) {
                  TASK_DAEMON_UNLOCK(ha);
!                 QL_PRINT_3(ha, "offline done\n");
                  return (FC_OFFLINE);
          }
          TASK_DAEMON_UNLOCK(ha);
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          ret = QL_SUCCESS;
  
!         if (CFG_IST(ha, CFG_N2N_SUPPORT) && ha->topology & QL_N_PORT) {
                  /*
                   * In p2p topology it sends a PLOGI after determining
                   * it has the N_Port login initiative.
                   */
                  ret = ql_p2p_plogi(ha, pkt);
*** 4972,4982 ****
  
                  /* Build ACC. */
                  acc.ls_code.ls_code = LA_ELS_ACC;
                  acc.common_service.fcph_version = 0x2006;
                  acc.common_service.cmn_features = 0x8800;
!                 acc.common_service.rx_bufsize = QL_MAX_FRAME_SIZE(ha);
                  acc.common_service.conc_sequences = 0xff;
                  acc.common_service.relative_offset = 0x03;
                  acc.common_service.e_d_tov = 0x7d0;
  
                  bcopy((void *)&tq->port_name[0],
--- 5325,5336 ----
  
                  /* Build ACC. */
                  acc.ls_code.ls_code = LA_ELS_ACC;
                  acc.common_service.fcph_version = 0x2006;
                  acc.common_service.cmn_features = 0x8800;
!                 acc.common_service.rx_bufsize =
!                     ha->loginparams.common_service.rx_bufsize;
                  acc.common_service.conc_sequences = 0xff;
                  acc.common_service.relative_offset = 0x03;
                  acc.common_service.e_d_tov = 0x7d0;
  
                  bcopy((void *)&tq->port_name[0],
*** 5000,5015 ****
                          rval = FC_TRAN_BUSY;
                  } else {
                          DEVICE_QUEUE_LOCK(tq);
                          tq->logout_sent = 0;
                          tq->flags &= ~TQF_NEED_AUTHENTICATION;
!                         if (CFG_IST(ha, CFG_CTRL_242581)) {
                                  tq->flags |= TQF_IIDMA_NEEDED;
                          }
                          DEVICE_QUEUE_UNLOCK(tq);
  
!                         if (CFG_IST(ha, CFG_CTRL_242581)) {
                                  TASK_DAEMON_LOCK(ha);
                                  ha->task_daemon_flags |= TD_IIDMA_NEEDED;
                                  TASK_DAEMON_UNLOCK(ha);
                          }
  
--- 5354,5369 ----
                          rval = FC_TRAN_BUSY;
                  } else {
                          DEVICE_QUEUE_LOCK(tq);
                          tq->logout_sent = 0;
                          tq->flags &= ~TQF_NEED_AUTHENTICATION;
!                         if (CFG_IST(ha, CFG_IIDMA_SUPPORT)) {
                                  tq->flags |= TQF_IIDMA_NEEDED;
                          }
                          DEVICE_QUEUE_UNLOCK(tq);
  
!                         if (CFG_IST(ha, CFG_IIDMA_SUPPORT)) {
                                  TASK_DAEMON_LOCK(ha);
                                  ha->task_daemon_flags |= TD_IIDMA_NEEDED;
                                  TASK_DAEMON_UNLOCK(ha);
                          }
  
*** 5064,5074 ****
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 5418,5428 ----
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 5093,5102 ****
--- 5447,5457 ----
          ql_tgt_t        tmp;
          ql_tgt_t        *tq = &tmp;
          int             rval;
          port_id_t       d_id;
          ql_srb_t        *sp = (ql_srb_t *)pkt->pkt_fca_private;
+         uint16_t        loop_id;
  
          tq->d_id.b.al_pa = 0;
          tq->d_id.b.area = 0;
          tq->d_id.b.domain = 0;
  
*** 5106,5121 ****
           * less unplesant than the error recovery if the wrong one is used.
           */
          for (id = 0; id <= LAST_LOCAL_LOOP_ID; id++) {
                  tq->loop_id = id;
                  rval = ql_get_port_database(ha, tq, PDF_NONE);
!                 EL(ha, "rval=%xh\n", rval);
                  /* check all the ones not logged in for possible use */
                  if (rval == QL_NOT_LOGGED_IN) {
                          if (tq->master_state == PD_STATE_PLOGI_PENDING) {
                                  ha->n_port->n_port_handle = tq->loop_id;
!                                 EL(ha, "n_port_handle =%xh, master state=%x\n",
                                      tq->loop_id, tq->master_state);
                                  break;
                          }
                          /*
                           * Use a 'port unavailable' entry only
--- 5461,5476 ----
           * less unplesant than the error recovery if the wrong one is used.
           */
          for (id = 0; id <= LAST_LOCAL_LOOP_ID; id++) {
                  tq->loop_id = id;
                  rval = ql_get_port_database(ha, tq, PDF_NONE);
!                 EL(ha, "rval=%xh, id=%x\n", rval, id);
                  /* check all the ones not logged in for possible use */
                  if (rval == QL_NOT_LOGGED_IN) {
                          if (tq->master_state == PD_STATE_PLOGI_PENDING) {
                                  ha->n_port->n_port_handle = tq->loop_id;
!                                 EL(ha, "loop_id=%xh, master state=%x\n",
                                      tq->loop_id, tq->master_state);
                                  break;
                          }
                          /*
                           * Use a 'port unavailable' entry only
*** 5122,5148 ****
                           * if we used it before.
                           */
                          if (tq->master_state == PD_STATE_PORT_UNAVAILABLE) {
                                  /* if the port_id matches, reuse it */
                                  if (pkt->pkt_cmd_fhdr.d_id == tq->d_id.b24) {
!                                         EL(ha, "n_port_handle =%xh,"
                                              "master state=%xh\n",
                                              tq->loop_id, tq->master_state);
                                          break;
                                  } else if (tq->loop_id ==
                                      ha->n_port->n_port_handle) {
!                                     // avoid a lint error
                                          uint16_t *hndl;
                                          uint16_t val;
  
                                          hndl = &ha->n_port->n_port_handle;
                                          val = *hndl;
                                          val++;
                                          val++;
                                          *hndl = val;
                                  }
!                         EL(ha, "rval=%xh, id=%d, n_port_handle =%xh, "
                              "master state=%x\n", rval, id, tq->loop_id,
                              tq->master_state);
                          }
  
                  }
--- 5477,5503 ----
                           * if we used it before.
                           */
                          if (tq->master_state == PD_STATE_PORT_UNAVAILABLE) {
                                  /* if the port_id matches, reuse it */
                                  if (pkt->pkt_cmd_fhdr.d_id == tq->d_id.b24) {
!                                         EL(ha, "n_port_handle loop_id=%xh, "
                                              "master state=%xh\n",
                                              tq->loop_id, tq->master_state);
                                          break;
                                  } else if (tq->loop_id ==
                                      ha->n_port->n_port_handle) {
!                                     /* avoid a lint error */
                                          uint16_t *hndl;
                                          uint16_t val;
  
                                          hndl = &ha->n_port->n_port_handle;
                                          val = *hndl;
                                          val++;
                                          val++;
                                          *hndl = val;
                                  }
!                         EL(ha, "rval=%xh, id=%d, n_port_handle loop_id=%xh, "
                              "master state=%x\n", rval, id, tq->loop_id,
                              tq->master_state);
                          }
  
                  }
*** 5151,5170 ****
                                  ha->n_port->n_port_handle = tq->loop_id;
                                  EL(ha, "n_port_handle =%xh, master state=%x\n",
                                      tq->loop_id, tq->master_state);
                                  break;
                          }
!                         EL(ha, "rval=%xh, id=%d, n_port_handle =%xh, "
                              "master state=%x\n", rval, id, tq->loop_id,
                              tq->master_state);
                  }
          }
          (void) ddi_dma_sync(pkt->pkt_cmd_dma, 0, 0, DDI_DMA_SYNC_FORDEV);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          tq = ql_d_id_to_queue(ha, d_id);
          ql_timeout_insert(ha, tq, sp);
          ql_start_iocb(ha, sp);
  
          return (QL_CONSUMED);
  }
  
--- 5506,5567 ----
                                  ha->n_port->n_port_handle = tq->loop_id;
                                  EL(ha, "n_port_handle =%xh, master state=%x\n",
                                      tq->loop_id, tq->master_state);
                                  break;
                          }
!                         EL(ha, "rval=%xh, id=%d, n_port_handle loop_id=%xh, "
                              "master state=%x\n", rval, id, tq->loop_id,
                              tq->master_state);
                  }
          }
          (void) ddi_dma_sync(pkt->pkt_cmd_dma, 0, 0, DDI_DMA_SYNC_FORDEV);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
+ 
+         /*
+          * In case fw does not have the loop id ready, driver assume 0 is
+          * used since this is p2p and there is only one remote port.
+          */
+         if (id == LAST_LOCAL_LOOP_ID + 1) {
+                 EL(ha, "out of range loop id; rval=%xh, id=%xh, d_id=%xh\n",
+                     rval, id, d_id.b24);
+         } else {
+                 EL(ha, "remote port loop_id '%x' has been logged in, d_id=%x\n",
+                     id, d_id.b24);
+         }
+ 
          tq = ql_d_id_to_queue(ha, d_id);
+ 
+         /*
+          * LV could use any d_id it likes.
+          * tq may not be available yet.
+          */
+         if (tq == NULL) {
+                 if (id != LAST_LOCAL_LOOP_ID + 1) {
+                         loop_id = id;
+                 } else {
+                         loop_id = 0;
+                 }
+                 /* Acquire adapter state lock. */
+                 ADAPTER_STATE_LOCK(ha);
+ 
+                 tq = ql_dev_init(ha, d_id, loop_id);
+ 
+                 ADAPTER_STATE_UNLOCK(ha);
+         }
+ 
+         /*
+          * Lun0 should always allocated since tq is
+          * derived from lun queue in ql_els_passthru_entry
+          * in the interrupt handler.
+          */
+         sp->lun_queue = ql_lun_queue(ha, tq, 0);
+ 
+         DEVICE_QUEUE_LOCK(tq);
          ql_timeout_insert(ha, tq, sp);
+         DEVICE_QUEUE_UNLOCK(tq);
+ 
          ql_start_iocb(ha, sp);
  
          return (QL_CONSUMED);
  }
  
*** 5192,5208 ****
          la_els_logi_t           acc;
          class_svc_param_t       *class3_param;
          int                     rval = FC_SUCCESS;
          int                     accept = 0;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             pkt->pkt_cmd_fhdr.d_id);
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
!         if (CFG_IST(ha, CFG_CTRL_2425) && ha->topology & QL_N_PORT) {
                  /*
                   * d_id of zero in a FLOGI accept response in a point to point
                   * topology triggers evaluation of N Port login initiative.
                   */
                  pkt->pkt_resp_fhdr.d_id = 0;
--- 5589,5604 ----
          la_els_logi_t           acc;
          class_svc_param_t       *class3_param;
          int                     rval = FC_SUCCESS;
          int                     accept = 0;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", pkt->pkt_cmd_fhdr.d_id);
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
!         if (CFG_IST(ha, CFG_N2N_SUPPORT) && ha->topology & QL_N_PORT) {
                  /*
                   * d_id of zero in a FLOGI accept response in a point to point
                   * topology triggers evaluation of N Port login initiative.
                   */
                  pkt->pkt_resp_fhdr.d_id = 0;
*** 5217,5230 ****
                  if (tq != NULL) {
                          /*
                           * If the target port has initiative send
                           * up a PLOGI about the new device.
                           */
!                         if ((ql_wwn_cmp(ha, (la_wwn_t *)&tq->port_name[0],
!                             (la_wwn_t *)(CFG_IST(ha, CFG_CTRL_2425) ?
!                             &ha->init_ctrl_blk.cb24.port_name[0] :
!                             &ha->init_ctrl_blk.cb.port_name[0])) == 1)) {
                                  ha->send_plogi_timer = 3;
                          } else {
                                  ha->send_plogi_timer = 0;
                          }
                          pkt->pkt_resp_fhdr.s_id = tq->d_id.b24;
--- 5613,5625 ----
                  if (tq != NULL) {
                          /*
                           * If the target port has initiative send
                           * up a PLOGI about the new device.
                           */
!                         if (ql_wwn_cmp(ha, (la_wwn_t *)tq->port_name,
!                             (la_wwn_t *)ha->loginparams.nport_ww_name.raw_wwn)
!                             == 1) {
                                  ha->send_plogi_timer = 3;
                          } else {
                                  ha->send_plogi_timer = 0;
                          }
                          pkt->pkt_resp_fhdr.s_id = tq->d_id.b24;
*** 5251,5267 ****
                          /* clear F_Port indicator */
                          acc.common_service.cmn_features = 0x0800;
                  } else {
                          acc.common_service.cmn_features = 0x1b00;
                  }
!                 CFG_IST(ha, CFG_CTRL_24258081) ?
!                     (acc.common_service.rx_bufsize = CHAR_TO_SHORT(
!                     ha->init_ctrl_blk.cb24.max_frame_length[0],
!                     ha->init_ctrl_blk.cb24.max_frame_length[1])) :
!                     (acc.common_service.rx_bufsize = CHAR_TO_SHORT(
!                     ha->init_ctrl_blk.cb.max_frame_length[0],
!                     ha->init_ctrl_blk.cb.max_frame_length[1]));
                  acc.common_service.conc_sequences = 0xff;
                  acc.common_service.relative_offset = 0x03;
                  acc.common_service.e_d_tov = 0x7d0;
                  if (accept) {
                          /* Use the saved N_Port WWNN and WWPN */
--- 5646,5657 ----
                          /* clear F_Port indicator */
                          acc.common_service.cmn_features = 0x0800;
                  } else {
                          acc.common_service.cmn_features = 0x1b00;
                  }
!                 acc.common_service.rx_bufsize =
!                     ha->loginparams.common_service.rx_bufsize;
                  acc.common_service.conc_sequences = 0xff;
                  acc.common_service.relative_offset = 0x03;
                  acc.common_service.e_d_tov = 0x7d0;
                  if (accept) {
                          /* Use the saved N_Port WWNN and WWPN */
*** 5309,5319 ****
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 5699,5709 ----
  
          if (rval != FC_SUCCESS) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 5335,5348 ****
  ql_els_logo(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          port_id_t       d_id;
          ql_tgt_t        *tq;
          la_els_logo_t   acc;
-         int             rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             pkt->pkt_cmd_fhdr.d_id);
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          tq = ql_d_id_to_queue(ha, d_id);
--- 5725,5736 ----
  ql_els_logo(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          port_id_t       d_id;
          ql_tgt_t        *tq;
          la_els_logo_t   acc;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", pkt->pkt_cmd_fhdr.d_id);
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          tq = ql_d_id_to_queue(ha, d_id);
*** 5386,5402 ****
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_prli
   *      Issue a extended link service process login request.
--- 5774,5786 ----
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_prli
   *      Issue a extended link service process login request.
*** 5420,5441 ****
          la_els_prli_t           acc;
          prli_svc_param_t        *param;
          ql_srb_t                *sp = (ql_srb_t *)pkt->pkt_fca_private;
          int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             pkt->pkt_cmd_fhdr.d_id);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          tq = ql_d_id_to_queue(ha, d_id);
          if (tq != NULL) {
                  (void) ql_get_port_database(ha, tq, PDF_NONE);
  
                  if ((ha->topology & QL_N_PORT) &&
                      (tq->master_state == PD_STATE_PLOGI_COMPLETED)) {
                          ql_timeout_insert(ha, tq, sp);
                          ql_start_iocb(ha, sp);
                          rval = QL_CONSUMED;
                  } else {
                          /* Build ACC. */
                          bzero(&acc, sizeof (acc));
--- 5804,5830 ----
          la_els_prli_t           acc;
          prli_svc_param_t        *param;
          ql_srb_t                *sp = (ql_srb_t *)pkt->pkt_fca_private;
          int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", pkt->pkt_cmd_fhdr.d_id);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          tq = ql_d_id_to_queue(ha, d_id);
          if (tq != NULL) {
                  (void) ql_get_port_database(ha, tq, PDF_NONE);
  
                  if ((ha->topology & QL_N_PORT) &&
                      (tq->master_state == PD_STATE_PLOGI_COMPLETED)) {
+ 
+                         /* always set lun_queue */
+                         sp->lun_queue = ql_lun_queue(ha, tq, 0);
+ 
+                         DEVICE_QUEUE_LOCK(tq);
                          ql_timeout_insert(ha, tq, sp);
+                         DEVICE_QUEUE_UNLOCK(tq);
                          ql_start_iocb(ha, sp);
                          rval = QL_CONSUMED;
                  } else {
                          /* Build ACC. */
                          bzero(&acc, sizeof (acc));
*** 5454,5482 ****
                              DDI_DEV_AUTOINCR);
  
                          pkt->pkt_state = FC_PKT_SUCCESS;
                  }
          } else {
                  la_els_rjt_t rjt;
  
                  /* Build RJT. */
                  bzero(&rjt, sizeof (rjt));
                  rjt.ls_code.ls_code = LA_ELS_RJT;
  
                  ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
!                     (uint8_t *)pkt->pkt_resp, sizeof (rjt), DDI_DEV_AUTOINCR);
  
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                  EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
          }
  
          if ((rval != FC_SUCCESS) && (rval != QL_CONSUMED)) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 5843,5897 ----
                              DDI_DEV_AUTOINCR);
  
                          pkt->pkt_state = FC_PKT_SUCCESS;
                  }
          } else {
+                 /* in case of P2P, tq might not have been created yet */
+                 if (ha->topology & QL_N_PORT) {
+ 
+                         /* Acquire adapter state lock. */
+                         ADAPTER_STATE_LOCK(ha);
+                         tq = ql_dev_init(ha, d_id, ha->n_port->n_port_handle);
+                         ADAPTER_STATE_UNLOCK(ha);
+ 
+                         /* always alloc lun #0 */
+                         sp->lun_queue = ql_lun_queue(ha, tq, 0);
+                         bcopy((void *)&ha->n_port->port_name[0],
+                             (void *) &tq->port_name[0], 8);
+                         bcopy((void *)&ha->n_port->node_name[0],
+                             (void *) &tq->node_name[0], 8);
+ 
+                         DEVICE_QUEUE_LOCK(tq);
+                         ql_timeout_insert(ha, tq, sp);
+                         DEVICE_QUEUE_UNLOCK(tq);
+ 
+                         ql_start_iocb(ha, sp);
+                         rval = QL_CONSUMED;
+ 
+                 } else {
+ 
                          la_els_rjt_t rjt;
  
                          /* Build RJT. */
                          bzero(&rjt, sizeof (rjt));
                          rjt.ls_code.ls_code = LA_ELS_RJT;
  
                          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&rjt,
!                             (uint8_t *)pkt->pkt_resp, sizeof (rjt),
!                             DDI_DEV_AUTOINCR);
  
                          pkt->pkt_state = FC_PKT_TRAN_ERROR;
                          pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                          EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
                  }
+         }
  
          if ((rval != FC_SUCCESS) && (rval != QL_CONSUMED)) {
                  EL(ha, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 5497,5510 ****
  /* ARGSUSED */
  static int
  ql_els_prlo(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          la_els_prli_t   acc;
-         int             rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             pkt->pkt_cmd_fhdr.d_id);
  
          /* Build ACC. */
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_cmd, sizeof (acc), DDI_DEV_AUTOINCR);
  
--- 5912,5923 ----
  /* ARGSUSED */
  static int
  ql_els_prlo(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          la_els_prli_t   acc;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", pkt->pkt_cmd_fhdr.d_id);
  
          /* Build ACC. */
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_cmd, sizeof (acc), DDI_DEV_AUTOINCR);
  
*** 5514,5530 ****
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
          pkt->pkt_state = FC_PKT_SUCCESS;
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_adisc
   *      Issue a extended link service address discovery request.
--- 5927,5939 ----
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
          pkt->pkt_state = FC_PKT_SUCCESS;
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_adisc
   *      Issue a extended link service address discovery request.
*** 5550,5562 ****
          ql_lun_t                *lq;
          port_id_t               d_id;
          la_els_adisc_t          acc;
          uint16_t                index, loop_id;
          ql_mbx_data_t           mr;
-         int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          /*
--- 5959,5970 ----
          ql_lun_t                *lq;
          port_id_t               d_id;
          la_els_adisc_t          acc;
          uint16_t                index, loop_id;
          ql_mbx_data_t           mr;
  
!         QL_PRINT_3(ha, "started\n");
  
          bzero(&acc, sizeof (acc));
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
  
          /*
*** 5647,5663 ****
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_linit
   *      Issue a extended link service loop initialize request.
--- 6055,6067 ----
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_linit
   *      Issue a extended link service loop initialize request.
*** 5678,5693 ****
  {
          ddi_dma_cookie_t        *cp;
          uint32_t                cnt;
          conv_num_t              n;
          port_id_t               d_id;
-         int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
!         if (ha->topology & QL_SNS_CONNECTION) {
                  fc_linit_req_t els;
                  lfa_cmd_t lfa;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
--- 6082,6096 ----
  {
          ddi_dma_cookie_t        *cp;
          uint32_t                cnt;
          conv_num_t              n;
          port_id_t               d_id;
  
!         QL_PRINT_3(ha, "started\n");
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
!         if (ha->topology & QL_FABRIC_CONNECTION) {
                  fc_linit_req_t els;
                  lfa_cmd_t lfa;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
*** 5742,5758 ****
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                  EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
          }
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_lpc
   *      Issue a extended link service loop control request.
--- 6145,6157 ----
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                  EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
          }
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_lpc
   *      Issue a extended link service loop control request.
*** 5773,5788 ****
  {
          ddi_dma_cookie_t        *cp;
          uint32_t                cnt;
          conv_num_t              n;
          port_id_t               d_id;
-         int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
!         if (ha->topology & QL_SNS_CONNECTION) {
                  ql_lpc_t els;
                  lfa_cmd_t lfa;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
--- 6172,6186 ----
  {
          ddi_dma_cookie_t        *cp;
          uint32_t                cnt;
          conv_num_t              n;
          port_id_t               d_id;
  
!         QL_PRINT_3(ha, "started\n");
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
!         if (ha->topology & QL_FABRIC_CONNECTION) {
                  ql_lpc_t els;
                  lfa_cmd_t lfa;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
*** 5813,5823 ****
                  lfa.addr[0] = n.size8[0];
                  lfa.addr[1] = n.size8[1];
                  lfa.addr[2] = n.size8[2];
                  lfa.subcommand[1] = 0x71;
                  lfa.payload[4] = els.port_control;
!                 bcopy((void *)&els.lpb[0], (void *)&lfa.payload[6], 32);
  
                  if (ql_send_lfa(ha, &lfa) != QL_SUCCESS) {
                          pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  } else {
                          pkt->pkt_state = FC_PKT_SUCCESS;
--- 6211,6221 ----
                  lfa.addr[0] = n.size8[0];
                  lfa.addr[1] = n.size8[1];
                  lfa.addr[2] = n.size8[2];
                  lfa.subcommand[1] = 0x71;
                  lfa.payload[4] = els.port_control;
!                 bcopy((void *)&els.lpb[0], (void *)&lfa.payload[6], 16);
  
                  if (ql_send_lfa(ha, &lfa) != QL_SUCCESS) {
                          pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  } else {
                          pkt->pkt_state = FC_PKT_SUCCESS;
*** 5835,5851 ****
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                  EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
          }
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_lsts
   *      Issue a extended link service loop status request.
--- 6233,6245 ----
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                  EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
          }
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_lsts
   *      Issue a extended link service loop status request.
*** 5866,5881 ****
  {
          ddi_dma_cookie_t        *cp;
          uint32_t                cnt;
          conv_num_t              n;
          port_id_t               d_id;
-         int                     rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
!         if (ha->topology & QL_SNS_CONNECTION) {
                  fc_lsts_req_t els;
                  lfa_cmd_t lfa;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
--- 6260,6274 ----
  {
          ddi_dma_cookie_t        *cp;
          uint32_t                cnt;
          conv_num_t              n;
          port_id_t               d_id;
  
!         QL_PRINT_3(ha, "started\n");
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
!         if (ha->topology & QL_FABRIC_CONNECTION) {
                  fc_lsts_req_t els;
                  lfa_cmd_t lfa;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
*** 5926,5942 ****
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                  EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
          }
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed=%xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_scr
   *      Issue a extended link service state change registration request.
--- 6319,6331 ----
                  pkt->pkt_state = FC_PKT_TRAN_ERROR;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                  EL(ha, "LA_ELS_RJT, FC_REASON_NO_CONNECTION\n");
          }
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_scr
   *      Issue a extended link service state change registration request.
*** 5954,5969 ****
   */
  static int
  ql_els_scr(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          fc_scr_resp_t   acc;
-         int             rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          bzero(&acc, sizeof (acc));
!         if (ha->topology & QL_SNS_CONNECTION) {
                  fc_scr_req_t els;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
  
--- 6343,6357 ----
   */
  static int
  ql_els_scr(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          fc_scr_resp_t   acc;
  
!         QL_PRINT_3(ha, "started\n");
  
          bzero(&acc, sizeof (acc));
!         if (ha->topology & QL_FABRIC_CONNECTION) {
                  fc_scr_req_t els;
  
                  ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
                      (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
  
*** 5991,6007 ****
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_rscn
   *      Issue a extended link service register state
--- 6379,6391 ----
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_rscn
   *      Issue a extended link service register state
*** 6020,6035 ****
   */
  static int
  ql_els_rscn(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          ql_rscn_resp_t  acc;
-         int             rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          bzero(&acc, sizeof (acc));
!         if (ha->topology & QL_SNS_CONNECTION) {
                  /* Build ACC. */
                  acc.scr_acc = LA_ELS_ACC;
  
                  pkt->pkt_state = FC_PKT_SUCCESS;
          } else {
--- 6404,6418 ----
   */
  static int
  ql_els_rscn(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          ql_rscn_resp_t  acc;
  
!         QL_PRINT_3(ha, "started\n");
  
          bzero(&acc, sizeof (acc));
!         if (ha->topology & QL_FABRIC_CONNECTION) {
                  /* Build ACC. */
                  acc.scr_acc = LA_ELS_ACC;
  
                  pkt->pkt_state = FC_PKT_SUCCESS;
          } else {
*** 6042,6058 ****
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_farp_req
   *      Issue FC Address Resolution Protocol (FARP)
--- 6425,6437 ----
          }
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_farp_req
   *      Issue FC Address Resolution Protocol (FARP)
*** 6069,6085 ****
   *      FC_TRANSPORT_ERROR - a transport error occurred.
   *
   * Context:
   *      Kernel context.
   */
  static int
  ql_els_farp_req(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          ql_acc_rjt_t    acc;
-         int             rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          bzero(&acc, sizeof (acc));
  
          /* Build ACC. */
          acc.ls_code.ls_code = LA_ELS_ACC;
--- 6448,6464 ----
   *      FC_TRANSPORT_ERROR - a transport error occurred.
   *
   * Context:
   *      Kernel context.
   */
+ /* ARGSUSED */
  static int
  ql_els_farp_req(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          ql_acc_rjt_t    acc;
  
!         QL_PRINT_3(ha, "started\n");
  
          bzero(&acc, sizeof (acc));
  
          /* Build ACC. */
          acc.ls_code.ls_code = LA_ELS_ACC;
*** 6087,6103 ****
          pkt->pkt_state = FC_PKT_SUCCESS;
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         if (rval != FC_SUCCESS) {
!                 EL(ha, "failed, rval = %xh\n", rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!         }
!         return (rval);
  }
  
  /*
   * ql_els_farp_reply
   *      Issue FC Address Resolution Protocol (FARP)
--- 6466,6478 ----
          pkt->pkt_state = FC_PKT_SUCCESS;
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_3(ha, "done\n");
! 
!         return (FC_SUCCESS);
  }
  
  /*
   * ql_els_farp_reply
   *      Issue FC Address Resolution Protocol (FARP)
*** 6119,6131 ****
  /* ARGSUSED */
  static int
  ql_els_farp_reply(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          ql_acc_rjt_t    acc;
-         int             rval = FC_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          bzero(&acc, sizeof (acc));
  
          /* Build ACC. */
          acc.ls_code.ls_code = LA_ELS_ACC;
--- 6494,6505 ----
  /* ARGSUSED */
  static int
  ql_els_farp_reply(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
          ql_acc_rjt_t    acc;
  
!         QL_PRINT_3(ha, "started\n");
  
          bzero(&acc, sizeof (acc));
  
          /* Build ACC. */
          acc.ls_code.ls_code = LA_ELS_ACC;
*** 6133,6145 ****
          pkt->pkt_state = FC_PKT_SUCCESS;
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
!         return (rval);
  }
  
  static int
  ql_els_rnid(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
--- 6507,6519 ----
          pkt->pkt_state = FC_PKT_SUCCESS;
  
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
!         QL_PRINT_3(ha, "done\n");
  
!         return (FC_SUCCESS);
  }
  
  static int
  ql_els_rnid(ql_adapter_state_t *ha, fc_packet_t *pkt)
  {
*** 6150,6160 ****
          uint16_t                index;
          la_els_rnid_acc_t       acc;
          la_els_rnid_t           *req;
          size_t                  req_len;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          req_len =  FCIO_RNID_MAX_DATA_LEN + sizeof (fc_rnid_hdr_t);
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          index = ql_alpa_to_index[d_id.b.al_pa];
  
--- 6524,6534 ----
          uint16_t                index;
          la_els_rnid_acc_t       acc;
          la_els_rnid_t           *req;
          size_t                  req_len;
  
!         QL_PRINT_3(ha, "started\n");
  
          req_len = FCIO_RNID_MAX_DATA_LEN + sizeof (fc_rnid_hdr_t);
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          index = ql_alpa_to_index[d_id.b.al_pa];
  
*** 6190,6207 ****
  
                  return (FC_FAILURE);
          }
  
          acc.ls_code.ls_code = LA_ELS_ACC;
!         bcopy(rnid_acc, &acc.hdr, req_len);
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
          kmem_free(rnid_acc, req_len);
          pkt->pkt_state = FC_PKT_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (FC_SUCCESS);
  }
  
  static int
--- 6564,6581 ----
  
                  return (FC_FAILURE);
          }
  
          acc.ls_code.ls_code = LA_ELS_ACC;
!         bcopy(rnid_acc, &acc.hdr, sizeof (fc_rnid_hdr_t));
          ddi_rep_put8(pkt->pkt_resp_acc, (uint8_t *)&acc,
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
          kmem_free(rnid_acc, req_len);
          pkt->pkt_state = FC_PKT_SUCCESS;
  
!         QL_PRINT_3(ha, "done\n");
  
          return (FC_SUCCESS);
  }
  
  static int
*** 6212,6222 ****
          ql_link_t               *link;
          ql_tgt_t                *tq;
          uint16_t                index;
          la_els_rls_acc_t        acc;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          tq = NULL;
--- 6586,6596 ----
          ql_link_t               *link;
          ql_tgt_t                *tq;
          uint16_t                index;
          la_els_rls_acc_t        acc;
  
!         QL_PRINT_3(ha, "started\n");
  
          d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          tq = NULL;
*** 6267,6277 ****
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
          kmem_free(rls_acc, sizeof (*rls_acc));
          pkt->pkt_state = FC_PKT_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (FC_SUCCESS);
  }
  
  static int
--- 6641,6651 ----
              (uint8_t *)pkt->pkt_resp, sizeof (acc), DDI_DEV_AUTOINCR);
  
          kmem_free(rls_acc, sizeof (*rls_acc));
          pkt->pkt_state = FC_PKT_SUCCESS;
  
!         QL_PRINT_3(ha, "done\n");
  
          return (FC_SUCCESS);
  }
  
  static int
*** 6282,6292 ****
          fc_unsol_buf_t  *ubp;
          ql_link_t       *link, *next_link;
          int             rval = FC_SUCCESS;
          int             cnt = 5;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /*
           * we need to ensure that q->outcnt == 0, otherwise
           * any cmd completed with PKT_PORT_OFFLINE after PLOGI
           * will confuse ulps.
--- 6656,6666 ----
          fc_unsol_buf_t  *ubp;
          ql_link_t       *link, *next_link;
          int             rval = FC_SUCCESS;
          int             cnt = 5;
  
!         QL_PRINT_3(ha, "started\n");
  
          /*
           * we need to ensure that q->outcnt == 0, otherwise
           * any cmd completed with PKT_PORT_OFFLINE after PLOGI
           * will confuse ulps.
*** 6321,6342 ****
           * return, if busy or if the plogi was asynchronous.
           */
          if ((rval != FC_SUCCESS) ||
              (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) &&
              pkt->pkt_comp)) {
!                 QL_PRINT_3(CE_CONT, "(%d): done, busy or async\n",
!                     ha->instance);
                  return (rval);
          }
  
          /*
           * Let us give daemon sufficient time and hopefully
           * when transport retries PLOGI, it would have flushed
           * callback queue.
           */
          TASK_DAEMON_LOCK(ha);
!         for (link = ha->callback_queue.first; link != NULL;
              link = next_link) {
                  next_link = link->next;
                  sp = link->base_address;
                  if (sp->flags & SRB_UB_CALLBACK) {
                          ubp = ha->ub_array[sp->handle];
--- 6695,6715 ----
           * return, if busy or if the plogi was asynchronous.
           */
          if ((rval != FC_SUCCESS) ||
              (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) &&
              pkt->pkt_comp)) {
!                 QL_PRINT_3(ha, "done, busy or async\n");
                  return (rval);
          }
  
          /*
           * Let us give daemon sufficient time and hopefully
           * when transport retries PLOGI, it would have flushed
           * callback queue.
           */
          TASK_DAEMON_LOCK(ha);
!         for (link = ha->unsol_callback_queue.first; link != NULL;
              link = next_link) {
                  next_link = link->next;
                  sp = link->base_address;
                  if (sp->flags & SRB_UB_CALLBACK) {
                          ubp = ha->ub_array[sp->handle];
*** 6351,6361 ****
                          break;
                  }
          }
          TASK_DAEMON_UNLOCK(ha);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 6724,6734 ----
                          break;
                  }
          }
          TASK_DAEMON_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 6381,6393 ****
          uint16_t                index;
          ql_tgt_t                *tq, *tq2;
          uint16_t                loop_id, first_loop_id, last_loop_id;
          int                     rval = QL_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             d_id.b24);
  
          /* Get head queue index. */
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          /* Check for device already has a queue. */
          tq = NULL;
--- 6754,6774 ----
          uint16_t                index;
          ql_tgt_t                *tq, *tq2;
          uint16_t                loop_id, first_loop_id, last_loop_id;
          int                     rval = QL_SUCCESS;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", d_id.b24);
  
+         /* Do not login vports */
+         for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
+                 if (vha->d_id.b24 == d_id.b24) {
+                         EL(ha, "failed=%xh, d_id=%xh vp_index=%xh\n",
+                             QL_FUNCTION_FAILED, d_id.b24, vha->vp_index);
+                         return (QL_FUNCTION_FAILED);
+                 }
+         }
+ 
          /* Get head queue index. */
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          /* Check for device already has a queue. */
          tq = NULL;
*** 6412,6423 ****
              !(tq->flags & TQF_FABRIC_DEVICE)) {
                  loop_id = (uint16_t)(tq->loop_id & ~PORT_LOST_ID);
          }
  
          /* Special case for Nameserver */
!         if (d_id.b24 == 0xFFFFFC) {
!                 loop_id = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
                      SNS_24XX_HDL : SIMPLE_NAME_SERVER_LOOP_ID);
                  if (tq == NULL) {
                          ADAPTER_STATE_LOCK(ha);
                          tq = ql_dev_init(ha, d_id, loop_id);
                          ADAPTER_STATE_UNLOCK(ha);
--- 6793,6810 ----
              !(tq->flags & TQF_FABRIC_DEVICE)) {
                  loop_id = (uint16_t)(tq->loop_id & ~PORT_LOST_ID);
          }
  
          /* Special case for Nameserver */
!         if (d_id.b24 == FS_NAME_SERVER) {
!                 if (!(ha->topology & QL_FABRIC_CONNECTION)) {
!                         EL(ha, "failed=%xh, d_id=%xh no fabric\n",
!                             QL_FUNCTION_FAILED, d_id.b24);
!                         return (QL_FUNCTION_FAILED);
!                 }
! 
!                 loop_id = (uint16_t)(CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
                      SNS_24XX_HDL : SIMPLE_NAME_SERVER_LOOP_ID);
                  if (tq == NULL) {
                          ADAPTER_STATE_LOCK(ha);
                          tq = ql_dev_init(ha, d_id, loop_id);
                          ADAPTER_STATE_UNLOCK(ha);
*** 6425,6444 ****
                                  EL(ha, "failed=%xh, d_id=%xh\n",
                                      QL_FUNCTION_FAILED, d_id.b24);
                                  return (QL_FUNCTION_FAILED);
                          }
                  }
!                 if (!(CFG_IST(ha, CFG_CTRL_8021))) {
                          rval = ql_login_fabric_port(ha, tq, loop_id);
                          if (rval == QL_SUCCESS) {
                                  tq->loop_id = loop_id;
                                  tq->flags |= TQF_FABRIC_DEVICE;
                                  (void) ql_get_port_database(ha, tq, PDF_NONE);
                          }
-                 } else {
-                         ha->topology = (uint8_t)
-                             (ha->topology | QL_SNS_CONNECTION);
                  }
          /* Check for device already logged in. */
          } else if (tq != NULL && VALID_DEVICE_ID(ha, loop_id)) {
                  if (tq->flags & TQF_FABRIC_DEVICE) {
                          rval = ql_login_fabric_port(ha, tq, loop_id);
--- 6812,6828 ----
                                  EL(ha, "failed=%xh, d_id=%xh\n",
                                      QL_FUNCTION_FAILED, d_id.b24);
                                  return (QL_FUNCTION_FAILED);
                          }
                  }
!                 if (!(CFG_IST(ha, CFG_CTRL_82XX))) {
                          rval = ql_login_fabric_port(ha, tq, loop_id);
                          if (rval == QL_SUCCESS) {
                                  tq->loop_id = loop_id;
                                  tq->flags |= TQF_FABRIC_DEVICE;
                                  (void) ql_get_port_database(ha, tq, PDF_NONE);
                          }
                  }
          /* Check for device already logged in. */
          } else if (tq != NULL && VALID_DEVICE_ID(ha, loop_id)) {
                  if (tq->flags & TQF_FABRIC_DEVICE) {
                          rval = ql_login_fabric_port(ha, tq, loop_id);
*** 6453,6465 ****
                                  DEVICE_QUEUE_LOCK(tq);
                                  tq->loop_id = loop_id;
                                  DEVICE_QUEUE_UNLOCK(tq);
                          }
                  }
!         } else if (ha->topology & QL_SNS_CONNECTION) {
                  /* Locate unused loop ID. */
!                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
                          first_loop_id = 0;
                          last_loop_id = LAST_N_PORT_HDL;
                  } else if (ha->topology & QL_F_PORT) {
                          first_loop_id = 0;
                          last_loop_id = SNS_LAST_LOOP_ID;
--- 6837,6849 ----
                                  DEVICE_QUEUE_LOCK(tq);
                                  tq->loop_id = loop_id;
                                  DEVICE_QUEUE_UNLOCK(tq);
                          }
                  }
!         } else if (ha->topology & QL_FABRIC_CONNECTION) {
                  /* Locate unused loop ID. */
!                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                          first_loop_id = 0;
                          last_loop_id = LAST_N_PORT_HDL;
                  } else if (ha->topology & QL_F_PORT) {
                          first_loop_id = 0;
                          last_loop_id = SNS_LAST_LOOP_ID;
*** 6532,6542 ****
--- 6916,6928 ----
                                  index = 1;
                                  break;
  
                          case QL_LOOP_ID_USED:
                                  tq->loop_id = PORT_NO_LOOP_ID;
+                                 ADAPTER_STATE_LOCK(ha);
                                  loop_id = ha->pha->free_loop_id++;
+                                 ADAPTER_STATE_UNLOCK(ha);
                                  break;
  
                          case QL_ALL_IDS_IN_USE:
                                  tq->loop_id = PORT_NO_LOOP_ID;
                                  index = 1;
*** 6555,6565 ****
          } else {
                  rval = QL_FUNCTION_FAILED;
          }
  
          if (rval != QL_SUCCESS) {
!                 EL(ha, "failed=%xh, d_id=%xh\n", rval, d_id.b24);
          } else {
                  EL(ha, "d_id=%xh, loop_id=%xh, "
                      "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n", tq->d_id.b24,
                      tq->loop_id, tq->port_name[0], tq->port_name[1],
                      tq->port_name[2], tq->port_name[3], tq->port_name[4],
--- 6941,6952 ----
          } else {
                  rval = QL_FUNCTION_FAILED;
          }
  
          if (rval != QL_SUCCESS) {
!                 EL(ha, "failed, rval=%xh, d_id=%xh\n",
!                     rval, d_id.b24);
          } else {
                  EL(ha, "d_id=%xh, loop_id=%xh, "
                      "wwpn=%02x%02x%02x%02x%02x%02x%02x%02xh\n", tq->d_id.b24,
                      tq->loop_id, tq->port_name[0], tq->port_name[1],
                      tq->port_name[2], tq->port_name[3], tq->port_name[4],
*** 6591,6619 ****
          int             retry = 0;
          port_id_t       d_id;
          ql_tgt_t        *newq;
          ql_mbx_data_t   mr;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             tq->d_id.b24);
  
          /*
!          * QL_PARAMETER_ERROR also means the firmware is
!          * not able to allocate PCB entry due to resource
!          * issues, or collision.
           */
          do {
                  rval = ql_login_fport(ha, tq, loop_id, LFF_NONE, &mr);
                  if ((rval == QL_PARAMETER_ERROR) ||
                      ((rval == QL_COMMAND_ERROR) && (mr.mb[1] == 2 ||
                      mr.mb[1] == 3 || mr.mb[1] == 7 || mr.mb[1] == 0xd))) {
                          retry++;
!                         drv_usecwait(10 * MILLISEC);
                  } else {
                          break;
                  }
!         } while (retry < 5);
  
          switch (rval) {
          case QL_SUCCESS:
                  tq->loop_id = loop_id;
                  break;
--- 6978,7004 ----
          int             retry = 0;
          port_id_t       d_id;
          ql_tgt_t        *newq;
          ql_mbx_data_t   mr;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", tq->d_id.b24);
  
          /*
!          * QL_PARAMETER_ERROR also means the firmware is not able to allocate
!          * PCB entry due to resource issues, or collision.
           */
          do {
                  rval = ql_login_fport(ha, tq, loop_id, LFF_NONE, &mr);
                  if ((rval == QL_PARAMETER_ERROR) ||
                      ((rval == QL_COMMAND_ERROR) && (mr.mb[1] == 2 ||
                      mr.mb[1] == 3 || mr.mb[1] == 7 || mr.mb[1] == 0xd))) {
                          retry++;
!                         drv_usecwait(ha->plogi_params->retry_dly_usec);
                  } else {
                          break;
                  }
!         } while (retry < ha->plogi_params->retry_cnt);
  
          switch (rval) {
          case QL_SUCCESS:
                  tq->loop_id = loop_id;
                  break;
*** 6644,6657 ****
                          /*
                           * This should NEVER ever happen; but this
                           * code is needed to bail out when the worst
                           * case happens - or as used to happen before
                           */
!                         QL_PRINT_2(CE_CONT, "(%d,%d): Loop ID is now "
                              "reassigned; old pairs: [%xh, %xh] and [%xh, %xh];"
                              "new pairs: [%xh, unknown] and [%xh, %xh]\n",
!                             ha->instance, ha->vp_index, tq->d_id.b24, loop_id,
                              newq->d_id.b24, newq->loop_id, tq->d_id.b24,
                              newq->d_id.b24, loop_id);
  
                          if ((newq->d_id.b24 & 0xff) != (d_id.b24 & 0xff)) {
                                  ADAPTER_STATE_LOCK(ha);
--- 7029,7042 ----
                          /*
                           * This should NEVER ever happen; but this
                           * code is needed to bail out when the worst
                           * case happens - or as used to happen before
                           */
!                         QL_PRINT_2(ha, "Loop ID is now "
                              "reassigned; old pairs: [%xh, %xh] and [%xh, %xh];"
                              "new pairs: [%xh, unknown] and [%xh, %xh]\n",
!                             tq->d_id.b24, loop_id,
                              newq->d_id.b24, newq->loop_id, tq->d_id.b24,
                              newq->d_id.b24, loop_id);
  
                          if ((newq->d_id.b24 & 0xff) != (d_id.b24 & 0xff)) {
                                  ADAPTER_STATE_LOCK(ha);
*** 6689,6701 ****
--- 7074,7089 ----
                          case 2:
                          case 3:
                                  rval = QL_MEMORY_ALLOC_FAILED;
                                  break;
  
+                         case 0xd:
                          case 4:
                                  rval = QL_FUNCTION_TIMEOUT;
                                  break;
+                         case 1:
+                         case 5:
                          case 7:
                                  rval = QL_FABRIC_NOT_INITIALIZED;
                                  break;
                          default:
                                  EL(ha, "cmd rtn; mb1=%xh\n", mr.mb[1]);
*** 6712,6722 ****
          if (rval != QL_SUCCESS && rval != QL_PORT_ID_USED &&
              rval != QL_LOOP_ID_USED) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 7100,7110 ----
          if (rval != QL_SUCCESS && rval != QL_PORT_ID_USED &&
              rval != QL_LOOP_ID_USED) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 6738,6748 ****
  {
          ql_link_t       *link;
          ql_tgt_t        *tq;
          uint16_t        index;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Get head queue index. */
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          /* Get device queue. */
--- 7126,7136 ----
  {
          ql_link_t       *link;
          ql_tgt_t        *tq;
          uint16_t        index;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Get head queue index. */
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          /* Get device queue. */
*** 6759,6769 ****
          if (tq != NULL && tq->flags & TQF_FABRIC_DEVICE) {
                  (void) ql_logout_fabric_port(ha, tq);
                  tq->loop_id = PORT_NO_LOOP_ID;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (QL_SUCCESS);
  }
  
  /*
--- 7147,7157 ----
          if (tq != NULL && tq->flags & TQF_FABRIC_DEVICE) {
                  (void) ql_logout_fabric_port(ha, tq);
                  tq->loop_id = PORT_NO_LOOP_ID;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (QL_SUCCESS);
  }
  
  /*
*** 6787,6803 ****
  {
          ql_link_t       *link;
          uint16_t        index;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh, loop_id=%xh\n",
!             ha->instance, d_id.b24, loop_id);
  
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          /* If device queue exists, set proper loop ID. */
-         tq = NULL;
          for (link = ha->dev[index].first; link != NULL; link = link->next) {
                  tq = link->base_address;
                  if (tq->d_id.b24 == d_id.b24) {
                          tq->loop_id = loop_id;
  
--- 7175,7189 ----
  {
          ql_link_t       *link;
          uint16_t        index;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started, d_id=%xh, loop_id=%xh\n", d_id.b24, loop_id);
  
          index = ql_alpa_to_index[d_id.b.al_pa];
  
          /* If device queue exists, set proper loop ID. */
          for (link = ha->dev[index].first; link != NULL; link = link->next) {
                  tq = link->base_address;
                  if (tq->d_id.b24 == d_id.b24) {
                          tq->loop_id = loop_id;
  
*** 6804,6830 ****
                          /* Reset port down retry count. */
                          tq->port_down_retry_count = ha->port_down_retry_count;
                          tq->qfull_retry_count = ha->qfull_retry_count;
  
                          break;
-                 } else {
-                         tq = NULL;
                  }
          }
  
          /* If device does not have queue. */
!         if (tq == NULL) {
                  tq = (ql_tgt_t *)kmem_zalloc(sizeof (ql_tgt_t), KM_SLEEP);
                  if (tq != NULL) {
                          /*
                           * mutex to protect the device queue,
                           * does not block interrupts.
                           */
                          mutex_init(&tq->mutex, NULL, MUTEX_DRIVER,
!                             (ha->iflags & IFLG_INTR_AIF) ?
!                             (void *)(uintptr_t)ha->intr_pri :
!                             (void *)(uintptr_t)ha->iblock_cookie);
  
                          tq->d_id.b24 = d_id.b24;
                          tq->loop_id = loop_id;
                          tq->device.base_address = tq;
                          tq->iidma_rate = IIDMA_RATE_INIT;
--- 7190,7212 ----
                          /* Reset port down retry count. */
                          tq->port_down_retry_count = ha->port_down_retry_count;
                          tq->qfull_retry_count = ha->qfull_retry_count;
  
                          break;
                  }
          }
  
          /* If device does not have queue. */
!         if (link == NULL) {
                  tq = (ql_tgt_t *)kmem_zalloc(sizeof (ql_tgt_t), KM_SLEEP);
                  if (tq != NULL) {
                          /*
                           * mutex to protect the device queue,
                           * does not block interrupts.
                           */
                          mutex_init(&tq->mutex, NULL, MUTEX_DRIVER,
!                             ha->intr_pri);
  
                          tq->d_id.b24 = d_id.b24;
                          tq->loop_id = loop_id;
                          tq->device.base_address = tq;
                          tq->iidma_rate = IIDMA_RATE_INIT;
*** 6840,6850 ****
  
          if (tq == NULL) {
                  EL(ha, "failed, d_id=%xh, loop_id=%xh\n", d_id.b24, loop_id);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (tq);
  }
  
  /*
--- 7222,7232 ----
  
          if (tq == NULL) {
                  EL(ha, "failed, d_id=%xh, loop_id=%xh\n", d_id.b24, loop_id);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (tq);
  }
  
  /*
*** 6864,6878 ****
  {
          ql_link_t       *link;
          uint16_t        index;
          ql_lun_t        *lq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          for (link = tq->lun_queues.first; link != NULL; link = link->next) {
                  lq = link->base_address;
                  if (lq->cmd.first != NULL) {
                          return;
                  }
          }
  
          if (tq->outcnt == 0) {
--- 7246,7262 ----
  {
          ql_link_t       *link;
          uint16_t        index;
          ql_lun_t        *lq;
  
!         QL_PRINT_3(ha, "started\n");
  
          for (link = tq->lun_queues.first; link != NULL; link = link->next) {
                  lq = link->base_address;
                  if (lq->cmd.first != NULL) {
+                         EL(ha, "cmd %ph pending in lq=%ph, lun=%xh\n",
+                             lq->cmd.first, lq, lq->lun_no);
                          return;
                  }
          }
  
          if (tq->outcnt == 0) {
*** 6898,6971 ****
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_lun_queue
   *      Allocate LUN queue if does not exists.
   *
   * Input:
   *      ha:     adapter state pointer.
   *      tq:     target queue.
!  *      lun:    LUN number.
   *
   * Returns:
   *      NULL = failure
   *
   * Context:
   *      Kernel context.
   */
  static ql_lun_t *
! ql_lun_queue(ql_adapter_state_t *ha, ql_tgt_t *tq, uint16_t lun)
  {
          ql_lun_t        *lq;
          ql_link_t       *link;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Fast path. */
!         if (tq->last_lun_queue != NULL && tq->last_lun_queue->lun_no == lun) {
!                 QL_PRINT_3(CE_CONT, "(%d): fast done\n", ha->instance);
                  return (tq->last_lun_queue);
          }
  
-         if (lun >= MAX_LUNS) {
-                 EL(ha, "Exceeded MAX_LUN=%d, lun=%d\n", MAX_LUNS, lun);
-                 return (NULL);
-         }
          /* If device queue exists, set proper loop ID. */
-         lq = NULL;
          for (link = tq->lun_queues.first; link != NULL; link = link->next) {
                  lq = link->base_address;
!                 if (lq->lun_no == lun) {
!                         QL_PRINT_3(CE_CONT, "(%d): found done\n", ha->instance);
                          tq->last_lun_queue = lq;
                          return (lq);
                  }
          }
  
!         /* If queue does exist. */
!         lq = (ql_lun_t *)kmem_zalloc(sizeof (ql_lun_t), KM_SLEEP);
  
!         /* Initialize LUN queue. */
          if (lq != NULL) {
                  lq->link.base_address = lq;
- 
-                 lq->lun_no = lun;
                  lq->target_queue = tq;
  
                  DEVICE_QUEUE_LOCK(tq);
                  ql_add_link_b(&tq->lun_queues, &lq->link);
                  DEVICE_QUEUE_UNLOCK(tq);
                  tq->last_lun_queue = lq;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (lq);
  }
  
  /*
--- 7282,7368 ----
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_lun_queue
   *      Allocate LUN queue if does not exists.
   *
   * Input:
   *      ha:     adapter state pointer.
   *      tq:             target queue.
!  *      lun_addr:       LUN number.
   *
   * Returns:
   *      NULL = failure
   *
   * Context:
   *      Kernel context.
   */
  static ql_lun_t *
! ql_lun_queue(ql_adapter_state_t *ha, ql_tgt_t *tq, uint64_t lun_addr)
  {
          ql_lun_t        *lq;
          ql_link_t       *link;
+         uint16_t        lun_no, lun_no_tmp;
+         fcp_ent_addr_t  *fcp_ent_addr = (fcp_ent_addr_t *)&lun_addr;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Fast path. */
!         if (tq->last_lun_queue != NULL && tq->last_lun_queue->lun_addr ==
!             lun_addr) {
!                 QL_PRINT_3(ha, "fast done\n");
                  return (tq->last_lun_queue);
          }
  
          /* If device queue exists, set proper loop ID. */
          for (link = tq->lun_queues.first; link != NULL; link = link->next) {
                  lq = link->base_address;
!                 if (lq->lun_addr == lun_addr) {
!                         QL_PRINT_3(ha, "found done\n");
                          tq->last_lun_queue = lq;
                          return (lq);
                  }
          }
  
!         /* Check the LUN addressing levels. */
!         if (fcp_ent_addr->ent_addr_1 != 0 || fcp_ent_addr->ent_addr_2 != 0 ||
!             fcp_ent_addr->ent_addr_3 != 0) {
!                 EL(ha, "Unsupported LUN Addressing level=0x%llxh", lun_addr);
!         }
  
!         lun_no_tmp = CHAR_TO_SHORT(lobyte(fcp_ent_addr->ent_addr_0),
!             hibyte(fcp_ent_addr->ent_addr_0));
! 
!         lun_no = lun_no_tmp & ~(QL_LUN_AM_MASK << 8);
! 
!         if (lun_no_tmp & (QL_LUN_AM_LUN << 8)) {
!                 EL(ha, "Unsupported first level LUN Addressing method=%xh, "
!                     "lun=%d(%xh)\n", lun_no_tmp & (QL_LUN_AM_MASK << 8),
!                     lun_no, lun_no_tmp);
!         }
! 
!         /* Create and initialize LUN queue. */
!         lq = (ql_lun_t *)kmem_zalloc(sizeof (ql_lun_t), KM_SLEEP);
          if (lq != NULL) {
                  lq->link.base_address = lq;
                  lq->target_queue = tq;
+                 lq->lun_addr = lun_addr;
+                 lq->lun_no = lun_no;
  
                  DEVICE_QUEUE_LOCK(tq);
                  ql_add_link_b(&tq->lun_queues, &lq->link);
                  DEVICE_QUEUE_UNLOCK(tq);
                  tq->last_lun_queue = lq;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (lq);
  }
  
  /*
*** 6988,7014 ****
  ql_fcp_scsi_cmd(ql_adapter_state_t *ha, fc_packet_t *pkt, ql_srb_t *sp)
  {
          port_id_t       d_id;
          ql_tgt_t        *tq;
          uint64_t        *ptr;
!         uint16_t        lun;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          tq = (ql_tgt_t *)pkt->pkt_fca_device;
          if (tq == NULL) {
                  d_id.r.rsvd_1 = 0;
                  d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
                  tq = ql_d_id_to_queue(ha, d_id);
          }
  
          sp->fcp = (struct fcp_cmd *)pkt->pkt_cmd;
!         lun = CHAR_TO_SHORT(lobyte(sp->fcp->fcp_ent_addr.ent_addr_0),
!             hibyte(sp->fcp->fcp_ent_addr.ent_addr_0));
! 
          if (tq != NULL &&
!             (sp->lun_queue = ql_lun_queue(ha, tq, lun)) != NULL) {
  
                  /*
                   * zero out FCP response; 24 Bytes
                   */
                  ptr = (uint64_t *)pkt->pkt_resp;
--- 7385,7409 ----
  ql_fcp_scsi_cmd(ql_adapter_state_t *ha, fc_packet_t *pkt, ql_srb_t *sp)
  {
          port_id_t       d_id;
          ql_tgt_t        *tq;
          uint64_t        *ptr;
!         uint64_t        fcp_ent_addr = 0;
  
!         QL_PRINT_3(ha, "started\n");
  
          tq = (ql_tgt_t *)pkt->pkt_fca_device;
          if (tq == NULL) {
                  d_id.r.rsvd_1 = 0;
                  d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
                  tq = ql_d_id_to_queue(ha, d_id);
          }
  
          sp->fcp = (struct fcp_cmd *)pkt->pkt_cmd;
!         fcp_ent_addr = *(uint64_t *)(&sp->fcp->fcp_ent_addr);
          if (tq != NULL &&
!             (sp->lun_queue = ql_lun_queue(ha, tq, fcp_ent_addr)) != NULL) {
  
                  /*
                   * zero out FCP response; 24 Bytes
                   */
                  ptr = (uint64_t *)pkt->pkt_resp;
*** 7041,7051 ****
                                              0, 0, DDI_DMA_SYNC_FORDEV);
                                  }
  
                                  /* Setup IOCB count. */
                                  if (pkt->pkt_data_cookie_cnt > ha->cmd_segs &&
!                                     (!CFG_IST(ha, CFG_CTRL_8021) ||
                                      sp->sg_dma.dma_handle == NULL)) {
                                          uint32_t        cnt;
  
                                          cnt = pkt->pkt_data_cookie_cnt -
                                              ha->cmd_segs;
--- 7436,7446 ----
                                              0, 0, DDI_DMA_SYNC_FORDEV);
                                  }
  
                                  /* Setup IOCB count. */
                                  if (pkt->pkt_data_cookie_cnt > ha->cmd_segs &&
!                                     (!CFG_IST(ha, CFG_CTRL_82XX) ||
                                      sp->sg_dma.dma_handle == NULL)) {
                                          uint32_t        cnt;
  
                                          cnt = pkt->pkt_data_cookie_cnt -
                                              ha->cmd_segs;
*** 7057,7079 ****
                                          } else {
                                                  sp->req_cnt++;
                                          }
                                  }
                          }
!                         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
                          return (ql_start_cmd(ha, tq, pkt, sp));
                  }
          } else {
                  pkt->pkt_state = FC_PKT_LOCAL_RJT;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
  
!                 if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp)
!                         ql_awaken_task_daemon(ha, sp, 0, 0);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (FC_SUCCESS);
  }
  
  /*
--- 7452,7475 ----
                                          } else {
                                                  sp->req_cnt++;
                                          }
                                  }
                          }
!                         QL_PRINT_3(ha, "done\n");
  
                          return (ql_start_cmd(ha, tq, pkt, sp));
                  }
          } else {
                  pkt->pkt_state = FC_PKT_LOCAL_RJT;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
  
!                 if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
!                         ql_io_comp(sp);
                  }
+         }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (FC_SUCCESS);
  }
  
  /*
*** 7093,7135 ****
  ql_task_mgmt(ql_adapter_state_t *ha, ql_tgt_t *tq, fc_packet_t *pkt,
      ql_srb_t *sp)
  {
          fcp_rsp_t               *fcpr;
          struct fcp_rsp_info     *rsp;
!         uint16_t                lun;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          fcpr = (fcp_rsp_t *)pkt->pkt_resp;
!         rsp = (struct fcp_rsp_info *)pkt->pkt_resp + sizeof (fcp_rsp_t);
  
          bzero(fcpr, pkt->pkt_rsplen);
  
          fcpr->fcp_u.fcp_status.rsp_len_set = 1;
          fcpr->fcp_response_len = 8;
-         lun = CHAR_TO_SHORT(lobyte(sp->fcp->fcp_ent_addr.ent_addr_0),
-             hibyte(sp->fcp->fcp_ent_addr.ent_addr_0));
  
          if (sp->fcp->fcp_cntl.cntl_clr_aca) {
!                 if (ql_clear_aca(ha, tq, lun) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_reset_lun) {
!                 if (ql_lun_reset(ha, tq, lun) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_reset_tgt) {
                  if (ql_target_reset(ha, tq, ha->loop_reset_delay) !=
                      QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_clr_tsk) {
!                 if (ql_clear_task_set(ha, tq, lun) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_abort_tsk) {
!                 if (ql_abort_task_set(ha, tq, lun) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else {
                  rsp->rsp_code = FCP_TASK_MGMT_NOT_SUPPTD;
          }
--- 7489,7529 ----
  ql_task_mgmt(ql_adapter_state_t *ha, ql_tgt_t *tq, fc_packet_t *pkt,
      ql_srb_t *sp)
  {
          fcp_rsp_t               *fcpr;
          struct fcp_rsp_info     *rsp;
!         ql_lun_t                *lq = sp->lun_queue;
  
!         QL_PRINT_3(ha, "started\n");
  
          fcpr = (fcp_rsp_t *)pkt->pkt_resp;
!         rsp = (struct fcp_rsp_info *)(pkt->pkt_resp + sizeof (fcp_rsp_t));
  
          bzero(fcpr, pkt->pkt_rsplen);
  
          fcpr->fcp_u.fcp_status.rsp_len_set = 1;
          fcpr->fcp_response_len = 8;
  
          if (sp->fcp->fcp_cntl.cntl_clr_aca) {
!                 if (ql_clear_aca(ha, tq, lq) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_reset_lun) {
!                 if (ql_lun_reset(ha, tq, lq) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_reset_tgt) {
                  if (ql_target_reset(ha, tq, ha->loop_reset_delay) !=
                      QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_clr_tsk) {
!                 if (ql_clear_task_set(ha, tq, lq) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else if (sp->fcp->fcp_cntl.cntl_abort_tsk) {
!                 if (ql_abort_task_set(ha, tq, lq) != QL_SUCCESS) {
                          rsp->rsp_code = FCP_TASK_MGMT_FAILED;
                  }
          } else {
                  rsp->rsp_code = FCP_TASK_MGMT_NOT_SUPPTD;
          }
*** 7136,7149 ****
  
          pkt->pkt_state = FC_PKT_SUCCESS;
  
          /* Do command callback. */
          if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
!                 ql_awaken_task_daemon(ha, sp, 0, 0);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_fcp_ip_cmd
   *      Process fibre channel (FCP) Internet (IP) protocols commands.
--- 7530,7543 ----
  
          pkt->pkt_state = FC_PKT_SUCCESS;
  
          /* Do command callback. */
          if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
!                 ql_io_comp(sp);
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_fcp_ip_cmd
   *      Process fibre channel (FCP) Internet (IP) protocols commands.
*** 7164,7174 ****
  ql_fcp_ip_cmd(ql_adapter_state_t *ha, fc_packet_t *pkt, ql_srb_t *sp)
  {
          port_id_t       d_id;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          tq = (ql_tgt_t *)pkt->pkt_fca_device;
          if (tq == NULL) {
                  d_id.r.rsvd_1 = 0;
                  d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
--- 7558,7568 ----
  ql_fcp_ip_cmd(ql_adapter_state_t *ha, fc_packet_t *pkt, ql_srb_t *sp)
  {
          port_id_t       d_id;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started\n");
  
          tq = (ql_tgt_t *)pkt->pkt_fca_device;
          if (tq == NULL) {
                  d_id.r.rsvd_1 = 0;
                  d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
*** 7195,7216 ****
                                  sp->req_cnt++;
                          }
                  } else {
                          sp->req_cnt = 1;
                  }
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
                  return (ql_start_cmd(ha, tq, pkt, sp));
          } else {
                  pkt->pkt_state = FC_PKT_LOCAL_RJT;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
  
                  if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp)
!                         ql_awaken_task_daemon(ha, sp, 0, 0);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (FC_SUCCESS);
  }
  
  /*
--- 7589,7610 ----
                                  sp->req_cnt++;
                          }
                  } else {
                          sp->req_cnt = 1;
                  }
!                 QL_PRINT_3(ha, "done\n");
  
                  return (ql_start_cmd(ha, tq, pkt, sp));
          } else {
                  pkt->pkt_state = FC_PKT_LOCAL_RJT;
                  pkt->pkt_reason = FC_REASON_NO_CONNECTION;
  
                  if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp)
!                         ql_io_comp(sp);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (FC_SUCCESS);
  }
  
  /*
*** 7237,7247 ****
          port_id_t       d_id;
          ql_tgt_t        *tq;
          ql_srb_t        *sp;
          int             rval;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&hdr,
              (uint8_t *)pkt->pkt_cmd, sizeof (hdr), DDI_DEV_AUTOINCR);
  
          bzero(&rjt, sizeof (rjt));
--- 7631,7641 ----
          port_id_t       d_id;
          ql_tgt_t        *tq;
          ql_srb_t        *sp;
          int             rval;
  
!         QL_PRINT_3(ha, "started\n");
  
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&hdr,
              (uint8_t *)pkt->pkt_cmd, sizeof (hdr), DDI_DEV_AUTOINCR);
  
          bzero(&rjt, sizeof (rjt));
*** 7256,7279 ****
--- 7650,7682 ----
          }
  
          switch (hdr.ct_fcstype) {
          case FCSTYPE_DIRECTORY:
          case FCSTYPE_MGMTSERVICE:
+ 
                  /* An FCA must make sure that the header is in big endian */
                  ql_cthdr_endian(pkt->pkt_cmd_acc, pkt->pkt_cmd, B_FALSE);
  
                  d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
                  tq = ql_d_id_to_queue(ha, d_id);
                  sp = (ql_srb_t *)pkt->pkt_fca_private;
+ 
                  if (tq == NULL ||
                      (sp->lun_queue = ql_lun_queue(ha, tq, 0)) == NULL) {
                          pkt->pkt_state = FC_PKT_LOCAL_RJT;
                          pkt->pkt_reason = FC_REASON_NO_CONNECTION;
                          rval = QL_SUCCESS;
                          break;
                  }
  
+                 if (tq->flags & TQF_LOGIN_NEEDED) {
+                         DEVICE_QUEUE_LOCK(tq);
+                         tq->flags &= ~TQF_LOGIN_NEEDED;
+                         DEVICE_QUEUE_UNLOCK(tq);
+                         (void) ql_login_fport(ha, tq, tq->loop_id, LFF_NONE,
+                             NULL);
+                 }
                  /*
                   * Services data is bound to pkt_cmd_dma
                   */
                  (void) ddi_dma_sync(pkt->pkt_cmd_dma, 0, 0,
                      DDI_DMA_SYNC_FORDEV);
*** 7284,7306 ****
                  /* Setup IOCB count. */
                  sp->iocb = ha->ms_cmd;
                  if (pkt->pkt_resp_cookie_cnt > MS_DATA_SEGMENTS) {
                          cnt = pkt->pkt_resp_cookie_cnt - MS_DATA_SEGMENTS;
                          sp->req_cnt =
!                             (uint16_t)(cnt / CONT_TYPE_1_DATA_SEGMENTS);
!                         if (cnt % CONT_TYPE_1_DATA_SEGMENTS) {
                                  sp->req_cnt = (uint16_t)(sp->req_cnt + 2);
                          } else {
                                  sp->req_cnt++;
                          }
                  } else {
                          sp->req_cnt = 1;
                  }
                  rval = ql_start_cmd(ha, tq, pkt, sp);
  
!                 QL_PRINT_3(CE_CONT, "(%d): done, ql_start_cmd=%xh\n",
!                     ha->instance, rval);
  
                  return (rval);
  
          default:
                  EL(ha, "unknown fcstype=%xh\n", hdr.ct_fcstype);
--- 7687,7708 ----
                  /* Setup IOCB count. */
                  sp->iocb = ha->ms_cmd;
                  if (pkt->pkt_resp_cookie_cnt > MS_DATA_SEGMENTS) {
                          cnt = pkt->pkt_resp_cookie_cnt - MS_DATA_SEGMENTS;
                          sp->req_cnt =
!                             (uint16_t)(cnt / ha->cmd_cont_segs);
!                         if (cnt % ha->cmd_cont_segs) {
                                  sp->req_cnt = (uint16_t)(sp->req_cnt + 2);
                          } else {
                                  sp->req_cnt++;
                          }
                  } else {
                          sp->req_cnt = 1;
                  }
                  rval = ql_start_cmd(ha, tq, pkt, sp);
  
!                 QL_PRINT_3(ha, "done, ql_start_cmd=%xh\n", rval);
  
                  return (rval);
  
          default:
                  EL(ha, "unknown fcstype=%xh\n", hdr.ct_fcstype);
*** 7321,7335 ****
                  EL(ha, "LA_ELS_RJT, FC_REASON_UNSUPPORTED\n");
          }
  
          /* Do command callback. */
          if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
!                 ql_awaken_task_daemon(ha, (ql_srb_t *)pkt->pkt_fca_private,
!                     0, 0);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (FC_SUCCESS);
  }
  
  /*
--- 7723,7736 ----
                  EL(ha, "LA_ELS_RJT, FC_REASON_UNSUPPORTED\n");
          }
  
          /* Do command callback. */
          if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) && pkt->pkt_comp) {
!                 ql_io_comp((ql_srb_t *)pkt->pkt_fca_private);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (FC_SUCCESS);
  }
  
  /*
*** 7435,7445 ****
  {
          int             rval = FC_SUCCESS;
          time_t          poll_wait = 0;
          ql_lun_t        *lq = sp->lun_queue;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          sp->handle = 0;
  
          /* Set poll for finish. */
          if (pkt->pkt_tran_flags & FC_TRAN_NO_INTR) {
--- 7836,7846 ----
  {
          int             rval = FC_SUCCESS;
          time_t          poll_wait = 0;
          ql_lun_t        *lq = sp->lun_queue;
  
!         QL_PRINT_3(ha, "started\n");
  
          sp->handle = 0;
  
          /* Set poll for finish. */
          if (pkt->pkt_tran_flags & FC_TRAN_NO_INTR) {
*** 7491,7501 ****
                  sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE;
  
                  /* Call done routine to handle completions. */
                  sp->cmd.next = NULL;
                  DEVICE_QUEUE_UNLOCK(tq);
!                 ql_done(&sp->cmd);
          } else {
                  if (ddi_in_panic() && (sp->flags & SRB_POLL)) {
                          int do_lip = 0;
  
                          DEVICE_QUEUE_UNLOCK(tq);
--- 7892,7902 ----
                  sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE;
  
                  /* Call done routine to handle completions. */
                  sp->cmd.next = NULL;
                  DEVICE_QUEUE_UNLOCK(tq);
!                 ql_done(&sp->cmd, B_FALSE);
          } else {
                  if (ddi_in_panic() && (sp->flags & SRB_POLL)) {
                          int do_lip = 0;
  
                          DEVICE_QUEUE_UNLOCK(tq);
*** 7539,7559 ****
                  }
          }
  
          /* If polling, wait for finish. */
          if (poll_wait) {
!                 if (ql_poll_cmd(ha, sp, poll_wait) != QL_SUCCESS) {
!                         int     res;
! 
!                         res = ql_abort((opaque_t)ha, pkt, 0);
!                         if (res != FC_SUCCESS && res != FC_ABORTED) {
!                                 DEVICE_QUEUE_LOCK(tq);
!                                 ql_remove_link(&lq->cmd, &sp->cmd);
!                                 sp->flags &= ~SRB_IN_DEVICE_QUEUE;
!                                 DEVICE_QUEUE_UNLOCK(tq);
                          }
-                 }
  
                  if (pkt->pkt_state != FC_PKT_SUCCESS) {
                          EL(ha, "failed, FC_TRANSPORT_ERROR\n");
                          rval = FC_TRANSPORT_ERROR;
                  }
--- 7940,7954 ----
                  }
          }
  
          /* If polling, wait for finish. */
          if (poll_wait) {
!                 if (ql_poll_cmd(ha, sp, poll_wait) != QL_SUCCESS &&
!                     pkt->pkt_state == FC_PKT_SUCCESS) {
!                         pkt->pkt_state = FC_PKT_TIMEOUT;
!                         pkt->pkt_reason = FC_REASON_HW_ERROR;
                  }
  
                  if (pkt->pkt_state != FC_PKT_SUCCESS) {
                          EL(ha, "failed, FC_TRANSPORT_ERROR\n");
                          rval = FC_TRANSPORT_ERROR;
                  }
*** 7571,7580 ****
--- 7966,7976 ----
                                  d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
                                  (void) ql_login_port(ha, d_id);
                          }
                  }
  
+                 (void) qlc_fm_check_pkt_dma_handle(ha, sp);
                  /*
                   * This should only happen during CPR dumping
                   */
                  if (!(pkt->pkt_tran_flags & FC_TRAN_NO_INTR) &&
                      pkt->pkt_comp) {
*** 7581,7591 ****
                          sp->flags &= ~SRB_POLL;
                          (*pkt->pkt_comp)(pkt);
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 7977,7987 ----
                          sp->flags &= ~SRB_POLL;
                          (*pkt->pkt_comp)(pkt);
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 7604,7623 ****
   *      Kernel context.
   */
  static int
  ql_poll_cmd(ql_adapter_state_t *vha, ql_srb_t *sp, time_t poll_wait)
  {
          int                     rval = QL_SUCCESS;
          time_t                  msecs_left = poll_wait * 100;   /* 10ms inc */
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          while (sp->flags & SRB_POLL) {
  
                  if ((ha->flags & INTERRUPTS_ENABLED) == 0 ||
!                     ha->idle_timer >= 15 || ddi_in_panic()) {
  
                          /* If waiting for restart, do it now. */
                          if (ha->port_retry_timer != 0) {
                                  ADAPTER_STATE_LOCK(ha);
                                  ha->port_retry_timer = 0;
--- 8000,8021 ----
   *      Kernel context.
   */
  static int
  ql_poll_cmd(ql_adapter_state_t *vha, ql_srb_t *sp, time_t poll_wait)
  {
+         uint32_t                index;
          int                     rval = QL_SUCCESS;
          time_t                  msecs_left = poll_wait * 100;   /* 10ms inc */
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(ha, "started\n");
  
          while (sp->flags & SRB_POLL) {
  
                  if ((ha->flags & INTERRUPTS_ENABLED) == 0 ||
!                     ha->idle_timer >= 15 || ddi_in_panic() ||
!                     curthread->t_flag & T_INTR_THREAD) {
  
                          /* If waiting for restart, do it now. */
                          if (ha->port_retry_timer != 0) {
                                  ADAPTER_STATE_LOCK(ha);
                                  ha->port_retry_timer = 0;
*** 7626,7662 ****
                                  TASK_DAEMON_LOCK(ha);
                                  ha->task_daemon_flags |= PORT_RETRY_NEEDED;
                                  TASK_DAEMON_UNLOCK(ha);
                          }
  
                          if (INTERRUPT_PENDING(ha)) {
!                                 (void) ql_isr((caddr_t)ha);
                                  INTR_LOCK(ha);
                                  ha->intr_claimed = TRUE;
                                  INTR_UNLOCK(ha);
                          }
  
                          /*
                           * Call task thread function in case the
                           * daemon is not running.
                           */
                          TASK_DAEMON_LOCK(ha);
  
                          if (!ddi_in_panic() && QL_DAEMON_NOT_ACTIVE(ha) &&
                              QL_TASK_PENDING(ha)) {
-                                 ha->task_daemon_flags |= TASK_THREAD_CALLED;
                                  ql_task_thread(ha);
-                                 ha->task_daemon_flags &= ~TASK_THREAD_CALLED;
                          }
  
                          TASK_DAEMON_UNLOCK(ha);
                  }
  
!                 if (msecs_left < 10) {
                          rval = QL_FUNCTION_TIMEOUT;
                          break;
                  }
  
                  /*
                   * Polling interval is 10 milli seconds; Increasing
                   * the polling interval to seconds since disk IO
                   * timeout values are ~60 seconds is tempting enough,
--- 8024,8088 ----
                                  TASK_DAEMON_LOCK(ha);
                                  ha->task_daemon_flags |= PORT_RETRY_NEEDED;
                                  TASK_DAEMON_UNLOCK(ha);
                          }
  
+                         ADAPTER_STATE_LOCK(ha);
+                         ha->flags |= POLL_INTR;
+                         ADAPTER_STATE_UNLOCK(ha);
+ 
                          if (INTERRUPT_PENDING(ha)) {
!                                 (void) ql_isr_aif((caddr_t)ha, 0);
                                  INTR_LOCK(ha);
                                  ha->intr_claimed = TRUE;
                                  INTR_UNLOCK(ha);
                          }
+                         if (ha->flags & NO_INTR_HANDSHAKE) {
+                                 for (index = 0; index < ha->rsp_queues_cnt;
+                                     index++) {
+                                         (void) ql_isr_aif((caddr_t)ha,
+                                             (caddr_t)((uintptr_t)(index + 1)));
+                                 }
+                         }
  
+                         ADAPTER_STATE_LOCK(ha);
+                         ha->flags &= ~POLL_INTR;
+                         ADAPTER_STATE_UNLOCK(ha);
+ 
                          /*
                           * Call task thread function in case the
                           * daemon is not running.
                           */
                          TASK_DAEMON_LOCK(ha);
  
                          if (!ddi_in_panic() && QL_DAEMON_NOT_ACTIVE(ha) &&
                              QL_TASK_PENDING(ha)) {
                                  ql_task_thread(ha);
                          }
  
                          TASK_DAEMON_UNLOCK(ha);
                  }
  
!                 if (msecs_left == 0) {
!                         if (rval == QL_SUCCESS) {
!                                 EL(ha, "timeout\n");
                                  rval = QL_FUNCTION_TIMEOUT;
+                                 if (ql_abort_io(ha, sp) == QL_SUCCESS) {
+                                         sp->pkt->pkt_reason = CS_ABORTED;
+                                         sp->cmd.next = NULL;
+                                         ql_done(&sp->cmd, B_FALSE);
                                          break;
                                  }
+                                 sp->flags |= SRB_COMMAND_TIMEOUT;
+                                 EL(ha, "abort failed, isp_abort_needed\n");
+                                 ql_awaken_task_daemon(ha, NULL,
+                                     ISP_ABORT_NEEDED, 0);
+                                 msecs_left = 30 * 100;
+                         } else {
+                                 break;
+                         }
+                 }
  
                  /*
                   * Polling interval is 10 milli seconds; Increasing
                   * the polling interval to seconds since disk IO
                   * timeout values are ~60 seconds is tempting enough,
*** 7667,7677 ****
                   */
                  ql_delay(ha, 10000);
                  msecs_left -= 10;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 8093,8103 ----
                   */
                  ql_delay(ha, 10000);
                  msecs_left -= 10;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 7695,7710 ****
          ql_srb_t                *sp;
          ql_link_t               *link;
          ql_tgt_t                *tq = lq->target_queue;
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (ddi_in_panic()) {
                  DEVICE_QUEUE_UNLOCK(tq);
!                 QL_PRINT_3(CE_CONT, "(%d): panic/active exit\n",
!                     ha->instance);
                  return;
          }
  
          while ((link = lq->cmd.first) != NULL) {
                  sp = link->base_address;
--- 8121,8135 ----
          ql_srb_t                *sp;
          ql_link_t               *link;
          ql_tgt_t                *tq = lq->target_queue;
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (ddi_in_panic()) {
                  DEVICE_QUEUE_UNLOCK(tq);
!                 QL_PRINT_3(ha, "panic/active exit\n");
                  return;
          }
  
          while ((link = lq->cmd.first) != NULL) {
                  sp = link->base_address;
*** 7711,7727 ****
  
                  /* Exit if can not start commands. */
                  if (DRIVER_SUSPENDED(ha) ||
                      (ha->flags & ONLINE) == 0 ||
                      !VALID_DEVICE_ID(ha, tq->loop_id) ||
-                     sp->flags & SRB_ABORT ||
                      tq->flags & (TQF_RSCN_RCVD | TQF_NEED_AUTHENTICATION |
                      TQF_QUEUE_SUSPENDED)) {
                          EL(vha, "break, d_id=%xh, tdf=%xh, tqf=%xh, spf=%xh, "
!                             "haf=%xh, loop_id=%xh\n", tq->d_id.b24,
                              ha->task_daemon_flags, tq->flags, sp->flags,
!                             ha->flags, tq->loop_id);
                          break;
                  }
  
                  /*
                   * Find out the LUN number for untagged command use.
--- 8136,8151 ----
  
                  /* Exit if can not start commands. */
                  if (DRIVER_SUSPENDED(ha) ||
                      (ha->flags & ONLINE) == 0 ||
                      !VALID_DEVICE_ID(ha, tq->loop_id) ||
                      tq->flags & (TQF_RSCN_RCVD | TQF_NEED_AUTHENTICATION |
                      TQF_QUEUE_SUSPENDED)) {
                          EL(vha, "break, d_id=%xh, tdf=%xh, tqf=%xh, spf=%xh, "
!                             "haf=%xh, loop_id=%xh sp=%ph\n", tq->d_id.b24,
                              ha->task_daemon_flags, tq->flags, sp->flags,
!                             ha->flags, tq->loop_id, sp);
                          break;
                  }
  
                  /*
                   * Find out the LUN number for untagged command use.
*** 7730,7741 ****
                   * or if reached LUN execution throttle.
                   */
                  if (sp->flags & SRB_FCP_CMD_PKT) {
                          if (lq->flags & LQF_UNTAGGED_PENDING ||
                              lq->lun_outcnt >= ha->execution_throttle) {
!                                 QL_PRINT_8(CE_CONT, "(%d): break, d_id=%xh, "
!                                     "lf=%xh, lun_outcnt=%xh\n", ha->instance,
                                      tq->d_id.b24, lq->flags, lq->lun_outcnt);
                                  break;
                          }
                          if (sp->fcp->fcp_cntl.cntl_qtype ==
                              FCP_QTYPE_UNTAGGED) {
--- 8154,8165 ----
                   * or if reached LUN execution throttle.
                   */
                  if (sp->flags & SRB_FCP_CMD_PKT) {
                          if (lq->flags & LQF_UNTAGGED_PENDING ||
                              lq->lun_outcnt >= ha->execution_throttle) {
!                                 QL_PRINT_8(ha, "break, d_id=%xh, "
!                                     "lf=%xh, lun_outcnt=%xh\n",
                                      tq->d_id.b24, lq->flags, lq->lun_outcnt);
                                  break;
                          }
                          if (sp->fcp->fcp_cntl.cntl_qtype ==
                              FCP_QTYPE_UNTAGGED) {
*** 7761,7819 ****
          }
  
          /* Release device queue lock. */
          DEVICE_QUEUE_UNLOCK(tq);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_done
   *      Process completed commands.
   *
   * Input:
   *      link:   first command link in chain.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
! ql_done(ql_link_t *link)
  {
          ql_adapter_state_t      *ha;
          ql_link_t               *next_link;
          ql_srb_t                *sp;
          ql_tgt_t                *tq;
          ql_lun_t                *lq;
  
!         QL_PRINT_3(CE_CONT, "started\n");
  
          for (; link != NULL; link = next_link) {
                  next_link = link->next;
                  sp = link->base_address;
                  ha = sp->ha;
  
                  if (sp->flags & SRB_UB_CALLBACK) {
                          QL_UB_LOCK(ha);
                          if (sp->flags & SRB_UB_IN_ISP) {
                                  if (ha->ub_outcnt != 0) {
                                          ha->ub_outcnt--;
                                  }
!                                 QL_UB_UNLOCK(ha);
!                                 ql_isp_rcvbuf(ha);
!                                 QL_UB_LOCK(ha);
                          }
                          QL_UB_UNLOCK(ha);
!                         ql_awaken_task_daemon(ha, sp, 0, 0);
                  } else {
                          /* Free outstanding command slot. */
                          if (sp->handle != 0) {
!                                 ha->outstanding_cmds[
                                      sp->handle & OSC_INDEX_MASK] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          }
  
                          /* Acquire device queue lock. */
                          lq = sp->lun_queue;
                          tq = lq->target_queue;
                          DEVICE_QUEUE_LOCK(tq);
--- 8185,8252 ----
          }
  
          /* Release device queue lock. */
          DEVICE_QUEUE_UNLOCK(tq);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_done
   *      Process completed commands.
   *
   * Input:
   *      link:   first command link in chain.
+  *      cmplt:  do command complete call back.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
! ql_done(ql_link_t *link, boolean_t cmplt)
  {
          ql_adapter_state_t      *ha;
          ql_link_t               *next_link;
          ql_srb_t                *sp;
          ql_tgt_t                *tq;
          ql_lun_t                *lq;
+         uint64_t                set_flags;
  
!         QL_PRINT_3(NULL, "started\n");
  
          for (; link != NULL; link = next_link) {
                  next_link = link->next;
                  sp = link->base_address;
+                 link->prev = link->next = NULL;
+                 link->head = NULL;
                  ha = sp->ha;
+                 set_flags = 0;
  
                  if (sp->flags & SRB_UB_CALLBACK) {
                          QL_UB_LOCK(ha);
                          if (sp->flags & SRB_UB_IN_ISP) {
                                  if (ha->ub_outcnt != 0) {
                                          ha->ub_outcnt--;
                                  }
!                                 if (ha->flags & IP_ENABLED) {
!                                         set_flags |= NEED_UNSOLICITED_BUFFERS;
                                  }
+                         }
                          QL_UB_UNLOCK(ha);
!                         ql_awaken_task_daemon(ha, sp, set_flags, 0);
                  } else {
                          /* Free outstanding command slot. */
+                         INTR_LOCK(ha);
                          if (sp->handle != 0) {
!                                 EL(ha, "free sp=%ph, sp->hdl=%xh\n",
!                                     (void *)sp, sp->handle);
!                                 ha->pha->outstanding_cmds[
                                      sp->handle & OSC_INDEX_MASK] = NULL;
                                  sp->handle = 0;
                                  sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                          }
+                         INTR_UNLOCK(ha);
  
                          /* Acquire device queue lock. */
                          lq = sp->lun_queue;
                          tq = lq->target_queue;
                          DEVICE_QUEUE_LOCK(tq);
*** 7872,7882 ****
                                  sp->wdg_q_time = sp->init_wdg_q_time;
  
                                  /* Issue marker command on reset status. */
                                  if (!(ha->task_daemon_flags & LOOP_DOWN) &&
                                      (sp->pkt->pkt_reason == CS_RESET ||
!                                     (CFG_IST(ha, CFG_CTRL_24258081) &&
                                      sp->pkt->pkt_reason == CS_ABORTED))) {
                                          (void) ql_marker(ha, tq->loop_id, 0,
                                              MK_SYNC_ID);
                                  }
  
--- 8305,8315 ----
                                  sp->wdg_q_time = sp->init_wdg_q_time;
  
                                  /* Issue marker command on reset status. */
                                  if (!(ha->task_daemon_flags & LOOP_DOWN) &&
                                      (sp->pkt->pkt_reason == CS_RESET ||
!                                     (CFG_IST(ha, CFG_ISP_FW_TYPE_2) &&
                                      sp->pkt->pkt_reason == CS_ABORTED))) {
                                          (void) ql_marker(ha, tq->loop_id, 0,
                                              MK_SYNC_ID);
                                  }
  
*** 7914,7930 ****
                                  switch (sp->pkt->pkt_reason) {
                                  case CS_COMPLETE:
                                          sp->pkt->pkt_state = FC_PKT_SUCCESS;
                                          break;
                                  case CS_RESET:
-                                         /* Issue marker command. */
-                                         if (!(ha->task_daemon_flags &
-                                             LOOP_DOWN)) {
-                                                 (void) ql_marker(ha,
-                                                     tq->loop_id, 0,
-                                                     MK_SYNC_ID);
-                                         }
                                          sp->pkt->pkt_state =
                                              FC_PKT_PORT_OFFLINE;
                                          sp->pkt->pkt_reason =
                                              FC_REASON_ABORTED;
                                          break;
--- 8347,8356 ----
*** 7979,7988 ****
--- 8405,8415 ----
                                          }
                                          DEVICE_QUEUE_UNLOCK(tq);
                                          break;
  
                                  case CS_TRANSPORT:
+                                 case CS_DEV_NOT_READY:
                                          sp->pkt->pkt_state = FC_PKT_LOCAL_RJT;
                                          sp->pkt->pkt_reason =
                                              FC_PKT_TRAN_ERROR;
                                          break;
  
*** 8000,8026 ****
                                          sp->pkt->pkt_reason =
                                              FC_REASON_HW_ERROR;
                                          break;
                                  }
  
                                  /* Now call the pkt completion callback */
                                  if (sp->flags & SRB_POLL) {
                                          sp->flags &= ~SRB_POLL;
!                                 } else if (sp->pkt->pkt_comp) {
!                                         if (sp->pkt->pkt_tran_flags &
!                                             FC_TRAN_IMMEDIATE_CB) {
!                                                 (*sp->pkt->pkt_comp)(sp->pkt);
                                          } else {
!                                                 ql_awaken_task_daemon(ha, sp,
!                                                     0, 0);
                                          }
                                  }
                          }
                  }
-         }
  
!         QL_PRINT_3(CE_CONT, "done\n");
  }
  
  /*
   * ql_awaken_task_daemon
   *      Adds command completion callback to callback queue and/or
--- 8427,8452 ----
                                          sp->pkt->pkt_reason =
                                              FC_REASON_HW_ERROR;
                                          break;
                                  }
  
+                                 (void) qlc_fm_check_pkt_dma_handle(ha, sp);
+ 
                                  /* Now call the pkt completion callback */
                                  if (sp->flags & SRB_POLL) {
                                          sp->flags &= ~SRB_POLL;
!                                 } else if (cmplt == B_TRUE &&
!                                     sp->pkt->pkt_comp) {
!                                         (sp->pkt->pkt_comp)(sp->pkt);
                                  } else {
!                                         ql_io_comp(sp);
                                  }
                          }
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_awaken_task_daemon
   *      Adds command completion callback to callback queue and/or
*** 8035,8094 ****
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
  ql_awaken_task_daemon(ql_adapter_state_t *vha, ql_srb_t *sp,
!     uint32_t set_flags, uint32_t reset_flags)
  {
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Acquire task daemon lock. */
          TASK_DAEMON_LOCK(ha);
  
!         if (set_flags & ISP_ABORT_NEEDED) {
!                 if (ha->task_daemon_flags & ABORT_ISP_ACTIVE) {
!                         set_flags &= ~ISP_ABORT_NEEDED;
                  }
          }
  
!         ha->task_daemon_flags |= set_flags;
!         ha->task_daemon_flags &= ~reset_flags;
! 
!         if (QL_DAEMON_SUSPENDED(ha)) {
!                 if (sp != NULL) {
                          TASK_DAEMON_UNLOCK(ha);
  
!                         /* Do callback. */
                          if (sp->flags & SRB_UB_CALLBACK) {
!                                 ql_unsol_callback(sp);
                          } else {
!                                 (*sp->pkt->pkt_comp)(sp->pkt);
                          }
-                 } else {
-                         if (!(curthread->t_flag & T_INTR_THREAD) &&
-                             !(ha->task_daemon_flags & TASK_THREAD_CALLED)) {
-                                 ha->task_daemon_flags |= TASK_THREAD_CALLED;
-                                 ql_task_thread(ha);
-                                 ha->task_daemon_flags &= ~TASK_THREAD_CALLED;
                          }
  
!                         TASK_DAEMON_UNLOCK(ha);
!                 }
!         } else {
!                 if (sp != NULL) {
!                         ql_add_link_b(&ha->callback_queue, &sp->cmd);
!                 }
! 
!                 if (ha->task_daemon_flags & TASK_DAEMON_SLEEPING_FLG) {
                          cv_broadcast(&ha->cv_task_daemon);
                  }
                  TASK_DAEMON_UNLOCK(ha);
-         }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_task_daemon
   *      Thread that is awaken by the driver when a
--- 8461,8510 ----
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
  ql_awaken_task_daemon(ql_adapter_state_t *vha, ql_srb_t *sp,
!     uint64_t set_flags, uint64_t reset_flags)
  {
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(ha, "started, sp=%p set_flags=%llx reset_flags=%llx\n",
!             sp, set_flags, reset_flags);
  
          /* Acquire task daemon lock. */
          TASK_DAEMON_LOCK(ha);
  
!         if (set_flags) {
!                 ha->task_daemon_flags |= set_flags;
          }
+         if (reset_flags) {
+                 ha->task_daemon_flags &= ~reset_flags;
          }
  
!         if (!(ha->task_daemon_flags & TASK_DAEMON_ALIVE_FLG)) {
!                 EL(ha, "done, not alive dtf=%xh\n", ha->task_daemon_flags);
                  TASK_DAEMON_UNLOCK(ha);
+                 return;
+         }
  
!         if (sp != NULL) {
                  if (sp->flags & SRB_UB_CALLBACK) {
!                         ql_add_link_b(&ha->unsol_callback_queue, &sp->cmd);
                  } else {
!                         EL(ha, "sp=%p, spf=%xh is not SRB_UB_CALLBACK",
!                             sp->flags);
                  }
          }
  
!         if (!ha->driver_thread_awake) {
!                 QL_PRINT_3(ha, "driver_thread_awake\n");
                  cv_broadcast(&ha->cv_task_daemon);
          }
+ 
          TASK_DAEMON_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_task_daemon
   *      Thread that is awaken by the driver when a
*** 8103,8163 ****
  static void
  ql_task_daemon(void *arg)
  {
          ql_adapter_state_t      *ha = (void *)arg;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
-         CALLB_CPR_INIT(&ha->cprinfo, &ha->task_daemon_mutex, callb_generic_cpr,
-             "ql_task_daemon");
- 
          /* Acquire task daemon lock. */
          TASK_DAEMON_LOCK(ha);
  
-         ha->task_daemon_flags |= TASK_DAEMON_ALIVE_FLG;
- 
          while ((ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) == 0) {
                  ql_task_thread(ha);
  
-                 QL_PRINT_3(CE_CONT, "(%d): Going to sleep\n", ha->instance);
- 
                  /*
                   * Before we wait on the conditional variable, we
                   * need to check if STOP_FLG is set for us to terminate
                   */
                  if (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
                          break;
                  }
  
!                 /*LINTED [Solaris CALLB_CPR_SAFE_BEGIN Lint error]*/
!                 CALLB_CPR_SAFE_BEGIN(&ha->cprinfo);
! 
                  ha->task_daemon_flags |= TASK_DAEMON_SLEEPING_FLG;
  
                  /* If killed, stop task daemon */
                  if (cv_wait_sig(&ha->cv_task_daemon,
                      &ha->task_daemon_mutex) == 0) {
!                         ha->task_daemon_flags |= TASK_DAEMON_STOP_FLG;
                  }
  
                  ha->task_daemon_flags &= ~TASK_DAEMON_SLEEPING_FLG;
- 
-                 /*LINTED [Solaris CALLB_CPR_SAFE_END Lint error]*/
-                 CALLB_CPR_SAFE_END(&ha->cprinfo, &ha->task_daemon_mutex);
- 
-                 QL_PRINT_3(CE_CONT, "(%d): Awakened\n", ha->instance);
          }
  
!         ha->task_daemon_flags &= ~(TASK_DAEMON_STOP_FLG |
              TASK_DAEMON_ALIVE_FLG);
  
!         /*LINTED [Solaris CALLB_CPR_EXIT Lint error]*/
!         CALLB_CPR_EXIT(&ha->cprinfo);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
! 
!         thread_exit();
  }
  
  /*
   * ql_task_thread
   *      Thread run by daemon.
--- 8519,8564 ----
  static void
  ql_task_daemon(void *arg)
  {
          ql_adapter_state_t      *ha = (void *)arg;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Acquire task daemon lock. */
          TASK_DAEMON_LOCK(ha);
  
          while ((ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) == 0) {
                  ql_task_thread(ha);
  
                  /*
                   * Before we wait on the conditional variable, we
                   * need to check if STOP_FLG is set for us to terminate
                   */
                  if (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
                          break;
                  }
  
!                 QL_PRINT_3(ha, "Going to sleep\n");
                  ha->task_daemon_flags |= TASK_DAEMON_SLEEPING_FLG;
  
                  /* If killed, stop task daemon */
                  if (cv_wait_sig(&ha->cv_task_daemon,
                      &ha->task_daemon_mutex) == 0) {
!                         QL_PRINT_10(ha, "killed\n");
!                         break;
                  }
  
+                 QL_PRINT_3(ha, "Awakened\n");
                  ha->task_daemon_flags &= ~TASK_DAEMON_SLEEPING_FLG;
          }
  
!         ha->task_daemon_flags &= ~(TASK_DAEMON_SLEEPING_FLG |
              TASK_DAEMON_ALIVE_FLG);
  
!         TASK_DAEMON_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_task_thread
   *      Thread run by daemon.
*** 8170,8275 ****
   *      Kernel context.
   */
  static void
  ql_task_thread(ql_adapter_state_t *ha)
  {
!         int                     loop_again;
          ql_srb_t                *sp;
-         ql_head_t               *head;
          ql_link_t               *link;
          caddr_t                 msg;
          ql_adapter_state_t      *vha;
  
          do {
!                 QL_PRINT_3(CE_CONT, "(%d): task_daemon_flags=%xh\n",
!                     ha->instance, ha->task_daemon_flags);
  
!                 loop_again = FALSE;
  
                  QL_PM_LOCK(ha);
                  if (ha->power_level != PM_LEVEL_D0) {
                          QL_PM_UNLOCK(ha);
!                         ha->task_daemon_flags |= TASK_DAEMON_STALLED_FLG;
                          break;
                  }
                  QL_PM_UNLOCK(ha);
  
!                 /* IDC event. */
!                 if (ha->task_daemon_flags & IDC_EVENT) {
!                         ha->task_daemon_flags &= ~IDC_EVENT;
                          TASK_DAEMON_UNLOCK(ha);
!                         ql_process_idc_event(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = TRUE;
                  }
  
!                 if (ha->flags & ADAPTER_SUSPENDED || ha->task_daemon_flags &
                      (TASK_DAEMON_STOP_FLG | DRIVER_STALL) ||
!                     (ha->flags & ONLINE) == 0) {
                          ha->task_daemon_flags |= TASK_DAEMON_STALLED_FLG;
                          break;
                  }
                  ha->task_daemon_flags &= ~TASK_DAEMON_STALLED_FLG;
  
!                 if (ha->task_daemon_flags & ISP_ABORT_NEEDED) {
                          TASK_DAEMON_UNLOCK(ha);
!                         if (ha->log_parity_pause == B_TRUE) {
!                                 (void) ql_flash_errlog(ha,
!                                     FLASH_ERRLOG_PARITY_ERR, 0,
!                                     MSW(ha->parity_stat_err),
!                                     LSW(ha->parity_stat_err));
!                                 ha->log_parity_pause = B_FALSE;
!                         }
!                         ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = TRUE;
                  }
  
                  /* Idle Check. */
                  if (ha->task_daemon_flags & TASK_DAEMON_IDLE_CHK_FLG) {
                          ha->task_daemon_flags &= ~TASK_DAEMON_IDLE_CHK_FLG;
!                         if (!(ha->task_daemon_flags & QL_SUSPENDED)) {
                                  TASK_DAEMON_UNLOCK(ha);
                                  ql_idle_check(ha);
                                  TASK_DAEMON_LOCK(ha);
!                                 loop_again = TRUE;
                          }
                  }
  
                  /* Crystal+ port#0 bypass transition */
                  if (ha->task_daemon_flags & HANDLE_PORT_BYPASS_CHANGE) {
                          ha->task_daemon_flags &= ~HANDLE_PORT_BYPASS_CHANGE;
                          TASK_DAEMON_UNLOCK(ha);
                          (void) ql_initiate_lip(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = TRUE;
                  }
  
                  /* Abort queues needed. */
                  if (ha->task_daemon_flags & ABORT_QUEUES_NEEDED) {
                          ha->task_daemon_flags &= ~ABORT_QUEUES_NEEDED;
                          TASK_DAEMON_UNLOCK(ha);
                          ql_abort_queues(ha);
                          TASK_DAEMON_LOCK(ha);
                  }
  
                  /* Not suspended, awaken waiting routines. */
!                 if (!(ha->task_daemon_flags & QL_SUSPENDED) &&
                      ha->task_daemon_flags & SUSPENDED_WAKEUP_FLG) {
                          ha->task_daemon_flags &= ~SUSPENDED_WAKEUP_FLG;
                          cv_broadcast(&ha->cv_dr_suspended);
!                         loop_again = TRUE;
                  }
  
                  /* Handle RSCN changes. */
                  for (vha = ha; vha != NULL; vha = vha->vp_next) {
                          if (vha->task_daemon_flags & RSCN_UPDATE_NEEDED) {
                                  vha->task_daemon_flags &= ~RSCN_UPDATE_NEEDED;
                                  TASK_DAEMON_UNLOCK(ha);
                                  (void) ql_handle_rscn_update(vha);
                                  TASK_DAEMON_LOCK(ha);
!                                 loop_again = TRUE;
                          }
                  }
  
                  /* Handle state changes. */
                  for (vha = ha; vha != NULL; vha = vha->vp_next) {
--- 8571,8689 ----
   *      Kernel context.
   */
  static void
  ql_task_thread(ql_adapter_state_t *ha)
  {
!         boolean_t               loop_again;
          ql_srb_t                *sp;
          ql_link_t               *link;
          caddr_t                 msg;
          ql_adapter_state_t      *vha;
  
+         ha->driver_thread_awake++;
          do {
!                 loop_again = B_FALSE;
  
!                 if (ha->sf != ha->flags ||
!                     (ha->task_daemon_flags & ~DTF_EL_MSG_SKIP_FLGS) != ha->df ||
!                     ha->cf != ha->cfg_flags) {
!                         ha->sf = ha->flags;
!                         ha->df = ha->task_daemon_flags & ~DTF_EL_MSG_SKIP_FLGS;
!                         ha->cf = ha->cfg_flags;
!                         EL(ha, "df=%xh, sf=%xh, cf=%xh\n",
!                             ha->df, ha->sf, ha->cf);
!                 }
  
                  QL_PM_LOCK(ha);
                  if (ha->power_level != PM_LEVEL_D0) {
                          QL_PM_UNLOCK(ha);
!                         ha->task_daemon_flags |= DRIVER_STALL |
!                             TASK_DAEMON_STALLED_FLG;
                          break;
                  }
                  QL_PM_UNLOCK(ha);
  
!                 if (ha->flags & ADAPTER_SUSPENDED) {
!                         ha->task_daemon_flags |= TASK_DAEMON_STALLED_FLG;
!                         break;
!                 }
! 
!                 /* Handle FW IDC events. */
!                 while (ha->flags & (IDC_STALL_NEEDED | IDC_RESTART_NEEDED |
!                     IDC_ACK_NEEDED)) {
                          TASK_DAEMON_UNLOCK(ha);
!                         ql_idc(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = B_TRUE;
                  }
  
!                 if (ha->task_daemon_flags &
                      (TASK_DAEMON_STOP_FLG | DRIVER_STALL) ||
!                     !(ha->flags & ONLINE)) {
                          ha->task_daemon_flags |= TASK_DAEMON_STALLED_FLG;
                          break;
                  }
                  ha->task_daemon_flags &= ~TASK_DAEMON_STALLED_FLG;
  
!                 /* Store error log. */
!                 if (ha->errlog[0] != 0 &&
!                     !(ha->task_daemon_flags & ISP_ABORT_NEEDED)) {
                          TASK_DAEMON_UNLOCK(ha);
!                         (void) ql_flash_errlog(ha, ha->errlog[0],
!                             ha->errlog[1], ha->errlog[2], ha->errlog[3]);
!                         ha->errlog[0] = 0;
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = B_TRUE;
                  }
  
                  /* Idle Check. */
                  if (ha->task_daemon_flags & TASK_DAEMON_IDLE_CHK_FLG) {
                          ha->task_daemon_flags &= ~TASK_DAEMON_IDLE_CHK_FLG;
!                         if (!DRIVER_SUSPENDED(ha)) {
                                  TASK_DAEMON_UNLOCK(ha);
                                  ql_idle_check(ha);
                                  TASK_DAEMON_LOCK(ha);
!                                 loop_again = B_TRUE;
                          }
                  }
  
                  /* Crystal+ port#0 bypass transition */
                  if (ha->task_daemon_flags & HANDLE_PORT_BYPASS_CHANGE) {
                          ha->task_daemon_flags &= ~HANDLE_PORT_BYPASS_CHANGE;
                          TASK_DAEMON_UNLOCK(ha);
                          (void) ql_initiate_lip(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = B_TRUE;
                  }
  
                  /* Abort queues needed. */
                  if (ha->task_daemon_flags & ABORT_QUEUES_NEEDED) {
                          ha->task_daemon_flags &= ~ABORT_QUEUES_NEEDED;
+                         if (ha->flags & ABORT_CMDS_LOOP_DOWN_TMO) {
                                  TASK_DAEMON_UNLOCK(ha);
                                  ql_abort_queues(ha);
                                  TASK_DAEMON_LOCK(ha);
+                                 loop_again = B_TRUE;
                          }
+                 }
  
                  /* Not suspended, awaken waiting routines. */
!                 if (!DRIVER_SUSPENDED(ha) &&
                      ha->task_daemon_flags & SUSPENDED_WAKEUP_FLG) {
                          ha->task_daemon_flags &= ~SUSPENDED_WAKEUP_FLG;
                          cv_broadcast(&ha->cv_dr_suspended);
!                         loop_again = B_TRUE;
                  }
  
                  /* Handle RSCN changes. */
                  for (vha = ha; vha != NULL; vha = vha->vp_next) {
                          if (vha->task_daemon_flags & RSCN_UPDATE_NEEDED) {
                                  vha->task_daemon_flags &= ~RSCN_UPDATE_NEEDED;
                                  TASK_DAEMON_UNLOCK(ha);
                                  (void) ql_handle_rscn_update(vha);
                                  TASK_DAEMON_LOCK(ha);
!                                 loop_again = B_TRUE;
                          }
                  }
  
                  /* Handle state changes. */
                  for (vha = ha; vha != NULL; vha = vha->vp_next) {
*** 8291,8300 ****
--- 8705,8715 ----
                                                  TASK_DAEMON_UNLOCK(ha);
                                                  ql_cmd_wait(ha);
                                                  TASK_DAEMON_LOCK(ha);
                                                  ha->task_daemon_flags &=
                                                      ~COMMAND_WAIT_ACTIVE;
+                                                 loop_again = B_TRUE;
                                          }
                                  }
  
                                  msg = NULL;
                                  if (FC_PORT_STATE_MASK(vha->state) ==
*** 8333,8376 ****
                                              "%s", QL_NAME, ha->instance,
                                              vha->vp_index, msg);
                                  }
  
                                  if (vha->flags & FCA_BOUND) {
!                                         QL_PRINT_10(CE_CONT, "(%d,%d): statec_"
!                                             "cb state=%xh\n", ha->instance,
!                                             vha->vp_index, vha->state);
                                          TASK_DAEMON_UNLOCK(ha);
                                          (vha->bind_info.port_statec_cb)
                                              (vha->bind_info.port_handle,
                                              vha->state);
                                          TASK_DAEMON_LOCK(ha);
                                  }
-                                 loop_again = TRUE;
                          }
                  }
  
!                 if (ha->task_daemon_flags & LIP_RESET_PENDING &&
!                     !(ha->task_daemon_flags & TASK_DAEMON_POWERING_DOWN)) {
!                         EL(ha, "processing LIP reset\n");
!                         ha->task_daemon_flags &= ~LIP_RESET_PENDING;
!                         TASK_DAEMON_UNLOCK(ha);
!                         for (vha = ha; vha != NULL; vha = vha->vp_next) {
!                                 if (vha->flags & FCA_BOUND) {
!                                         QL_PRINT_10(CE_CONT, "(%d,%d): statec_"
!                                             "cb reset\n", ha->instance,
!                                             vha->vp_index);
!                                         (vha->bind_info.port_statec_cb)
!                                             (vha->bind_info.port_handle,
!                                             FC_STATE_TARGET_PORT_RESET);
!                                 }
!                         }
!                         TASK_DAEMON_LOCK(ha);
!                         loop_again = TRUE;
!                 }
! 
!                 if (QL_IS_SET(ha->task_daemon_flags, NEED_UNSOLICITED_BUFFERS |
!                     FIRMWARE_UP)) {
                          /*
                           * The firmware needs more unsolicited
                           * buffers. We cannot allocate any new
                           * buffers unless the ULP module requests
                           * for new buffers. All we can do here is
--- 8748,8772 ----
                                              "%s", QL_NAME, ha->instance,
                                              vha->vp_index, msg);
                                  }
  
                                  if (vha->flags & FCA_BOUND) {
!                                         QL_PRINT_10(vha, "statec_"
!                                             "cb state=%xh\n",
!                                             vha->state);
                                          TASK_DAEMON_UNLOCK(ha);
                                          (vha->bind_info.port_statec_cb)
                                              (vha->bind_info.port_handle,
                                              vha->state);
                                          TASK_DAEMON_LOCK(ha);
+                                         loop_again = B_TRUE;
                                  }
                          }
                  }
  
!                 if (ha->task_daemon_flags & NEED_UNSOLICITED_BUFFERS &&
!                     ha->task_daemon_flags & FIRMWARE_UP) {
                          /*
                           * The firmware needs more unsolicited
                           * buffers. We cannot allocate any new
                           * buffers unless the ULP module requests
                           * for new buffers. All we can do here is
*** 8379,8426 ****
                           */
                          ha->task_daemon_flags &= ~NEED_UNSOLICITED_BUFFERS;
                          TASK_DAEMON_UNLOCK(ha);
                          ql_isp_rcvbuf(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = TRUE;
                  }
  
                  if (ha->task_daemon_flags & ISP_ABORT_NEEDED) {
                          TASK_DAEMON_UNLOCK(ha);
                          (void) ql_abort_isp(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = TRUE;
                  }
  
!                 if (!(ha->task_daemon_flags & (LOOP_DOWN | DRIVER_STALL |
!                     COMMAND_WAIT_NEEDED))) {
!                         if (QL_IS_SET(ha->task_daemon_flags,
!                             RESET_MARKER_NEEDED | FIRMWARE_UP)) {
!                                 ha->task_daemon_flags &= ~RESET_MARKER_NEEDED;
!                                 if (!(ha->task_daemon_flags & RESET_ACTIVE)) {
!                                         ha->task_daemon_flags |= RESET_ACTIVE;
                                          TASK_DAEMON_UNLOCK(ha);
                                          for (vha = ha; vha != NULL;
                                              vha = vha->vp_next) {
!                                                 ql_rst_aen(vha);
                                          }
                                          TASK_DAEMON_LOCK(ha);
!                                         ha->task_daemon_flags &= ~RESET_ACTIVE;
!                                         loop_again = TRUE;
                                  }
                          }
  
!                         if (QL_IS_SET(ha->task_daemon_flags,
!                             LOOP_RESYNC_NEEDED | FIRMWARE_UP)) {
                                  if (!(ha->task_daemon_flags &
                                      LOOP_RESYNC_ACTIVE)) {
                                          ha->task_daemon_flags |=
                                              LOOP_RESYNC_ACTIVE;
                                          TASK_DAEMON_UNLOCK(ha);
!                                         (void) ql_loop_resync(ha);
                                          TASK_DAEMON_LOCK(ha);
!                                         loop_again = TRUE;
                                  }
                          }
                  }
  
                  /* Port retry needed. */
--- 8775,8835 ----
                           */
                          ha->task_daemon_flags &= ~NEED_UNSOLICITED_BUFFERS;
                          TASK_DAEMON_UNLOCK(ha);
                          ql_isp_rcvbuf(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = B_TRUE;
                  }
  
+                 if (ha->task_daemon_flags & WATCHDOG_NEEDED) {
+                         ha->task_daemon_flags &= ~WATCHDOG_NEEDED;
+                         TASK_DAEMON_UNLOCK(ha);
+                         ql_watchdog(ha);
+                         TASK_DAEMON_LOCK(ha);
+                         loop_again = B_TRUE;
+                 }
+ 
                  if (ha->task_daemon_flags & ISP_ABORT_NEEDED) {
                          TASK_DAEMON_UNLOCK(ha);
                          (void) ql_abort_isp(ha);
                          TASK_DAEMON_LOCK(ha);
!                         loop_again = B_TRUE;
                  }
  
!                 if (!(ha->task_daemon_flags & (COMMAND_WAIT_NEEDED |
!                     ABORT_QUEUES_NEEDED | ISP_ABORT_NEEDED | LOOP_DOWN)) &&
!                     ha->task_daemon_flags & FIRMWARE_UP) {
!                         if (ha->task_daemon_flags & MARKER_NEEDED) {
!                                 if (!(ha->task_daemon_flags & MARKER_ACTIVE)) {
!                                         ha->task_daemon_flags |= MARKER_ACTIVE;
!                                         ha->task_daemon_flags &= ~MARKER_NEEDED;
                                          TASK_DAEMON_UNLOCK(ha);
                                          for (vha = ha; vha != NULL;
                                              vha = vha->vp_next) {
!                                                 (void) ql_marker(vha, 0, 0,
!                                                     MK_SYNC_ALL);
                                          }
                                          TASK_DAEMON_LOCK(ha);
!                                         ha->task_daemon_flags &= ~MARKER_ACTIVE;
!                                         TASK_DAEMON_UNLOCK(ha);
!                                         ql_restart_queues(ha);
!                                         TASK_DAEMON_LOCK(ha);
!                                         loop_again = B_TRUE;
!                                 } else {
!                                         ha->task_daemon_flags &= ~MARKER_NEEDED;
                                  }
                          }
  
!                         if (ha->task_daemon_flags & LOOP_RESYNC_NEEDED) {
                                  if (!(ha->task_daemon_flags &
                                      LOOP_RESYNC_ACTIVE)) {
                                          ha->task_daemon_flags |=
                                              LOOP_RESYNC_ACTIVE;
                                          TASK_DAEMON_UNLOCK(ha);
!                                         ql_loop_resync(ha);
                                          TASK_DAEMON_LOCK(ha);
!                                         loop_again = B_TRUE;
                                  }
                          }
                  }
  
                  /* Port retry needed. */
*** 8437,8447 ****
                  }
  
                  /* iiDMA setting needed? */
                  if (ha->task_daemon_flags & TD_IIDMA_NEEDED) {
                          ha->task_daemon_flags &= ~TD_IIDMA_NEEDED;
- 
                          TASK_DAEMON_UNLOCK(ha);
                          ql_iidma(ha);
                          TASK_DAEMON_LOCK(ha);
                          loop_again = B_TRUE;
                  }
--- 8846,8855 ----
*** 8449,8485 ****
                  if (ha->task_daemon_flags & SEND_PLOGI) {
                          ha->task_daemon_flags &= ~SEND_PLOGI;
                          TASK_DAEMON_UNLOCK(ha);
                          (void) ql_n_port_plogi(ha);
                          TASK_DAEMON_LOCK(ha);
                  }
  
!                 head = &ha->callback_queue;
!                 if (head->first != NULL) {
!                         sp = head->first->base_address;
                          link = &sp->cmd;
! 
!                         /* Dequeue command. */
!                         ql_remove_link(head, link);
! 
!                         /* Release task daemon lock. */
                          TASK_DAEMON_UNLOCK(ha);
- 
-                         /* Do callback. */
-                         if (sp->flags & SRB_UB_CALLBACK) {
                                  ql_unsol_callback(sp);
!                         } else {
!                                 (*sp->pkt->pkt_comp)(sp->pkt);
                          }
  
!                         /* Acquire task daemon lock. */
                          TASK_DAEMON_LOCK(ha);
  
!                         loop_again = TRUE;
                  }
  
!         } while (loop_again);
  }
  
  /*
   * ql_idle_check
   *      Test for adapter is alive and well.
--- 8857,8901 ----
                  if (ha->task_daemon_flags & SEND_PLOGI) {
                          ha->task_daemon_flags &= ~SEND_PLOGI;
                          TASK_DAEMON_UNLOCK(ha);
                          (void) ql_n_port_plogi(ha);
                          TASK_DAEMON_LOCK(ha);
+                         loop_again = B_TRUE;
                  }
  
!                 if (ha->unsol_callback_queue.first != NULL) {
!                         sp = (ha->unsol_callback_queue.first)->base_address;
                          link = &sp->cmd;
!                         ql_remove_link(&ha->unsol_callback_queue, link);
                          TASK_DAEMON_UNLOCK(ha);
                          ql_unsol_callback(sp);
!                         TASK_DAEMON_LOCK(ha);
!                         loop_again = B_TRUE;
                  }
  
!                 if (ha->task_daemon_flags & IDC_POLL_NEEDED) {
!                         ha->task_daemon_flags &= ~IDC_POLL_NEEDED;
!                         TASK_DAEMON_UNLOCK(ha);
!                         ql_8021_idc_poll(ha);
                          TASK_DAEMON_LOCK(ha);
+                         loop_again = B_TRUE;
+                 }
  
!                 if (ha->task_daemon_flags & LED_BLINK) {
!                         ha->task_daemon_flags &= ~LED_BLINK;
!                         TASK_DAEMON_UNLOCK(ha);
!                         ql_blink_led(ha);
!                         TASK_DAEMON_LOCK(ha);
!                         loop_again = B_TRUE;
                  }
  
!         } while (loop_again == B_TRUE);
! 
!         if (ha->driver_thread_awake) {
!                 ha->driver_thread_awake--;
!         }
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_idle_check
   *      Test for adapter is alive and well.
*** 8491,8526 ****
   *      Kernel context.
   */
  static void
  ql_idle_check(ql_adapter_state_t *ha)
  {
-         ddi_devstate_t  state;
          int             rval;
          ql_mbx_data_t   mr;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Firmware Ready Test. */
          rval = ql_get_firmware_state(ha, &mr);
!         if (!(ha->task_daemon_flags & QL_SUSPENDED) &&
              (rval != QL_SUCCESS || mr.mb[1] != FSTATE_READY)) {
                  EL(ha, "failed, Firmware Ready Test = %xh\n", rval);
-                 state = ddi_get_devstate(ha->dip);
-                 if (state == DDI_DEVSTATE_UP) {
-                         /*EMPTY*/
-                         ddi_dev_report_fault(ha->dip, DDI_SERVICE_DEGRADED,
-                             DDI_DEVICE_FAULT, "Firmware Ready Test failed");
-                 }
                  TASK_DAEMON_LOCK(ha);
                  if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
                          EL(ha, "fstate_ready, isp_abort_needed\n");
                          ha->task_daemon_flags |= ISP_ABORT_NEEDED;
                  }
                  TASK_DAEMON_UNLOCK(ha);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_unsol_callback
   *      Handle unsolicited buffer callbacks.
--- 8907,8935 ----
   *      Kernel context.
   */
  static void
  ql_idle_check(ql_adapter_state_t *ha)
  {
          int             rval;
          ql_mbx_data_t   mr;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Firmware Ready Test. */
          rval = ql_get_firmware_state(ha, &mr);
!         if (!DRIVER_SUSPENDED(ha) &&
              (rval != QL_SUCCESS || mr.mb[1] != FSTATE_READY)) {
                  EL(ha, "failed, Firmware Ready Test = %xh\n", rval);
                  TASK_DAEMON_LOCK(ha);
                  if (!(ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
                          EL(ha, "fstate_ready, isp_abort_needed\n");
                          ha->task_daemon_flags |= ISP_ABORT_NEEDED;
                  }
                  TASK_DAEMON_UNLOCK(ha);
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_unsol_callback
   *      Handle unsolicited buffer callbacks.
*** 8540,8550 ****
          uchar_t                 r_ctl;
          uchar_t                 ls_code;
          ql_tgt_t                *tq;
          ql_adapter_state_t      *ha = sp->ha, *pha = sp->ha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          ubp = ha->ub_array[sp->handle];
          r_ctl = ubp->ub_frame.r_ctl;
          ls_code = ubp->ub_buffer[0];
  
--- 8949,8959 ----
          uchar_t                 r_ctl;
          uchar_t                 ls_code;
          ql_tgt_t                *tq;
          ql_adapter_state_t      *ha = sp->ha, *pha = sp->ha->pha;
  
!         QL_PRINT_3(ha, "started\n");
  
          ubp = ha->ub_array[sp->handle];
          r_ctl = ubp->ub_frame.r_ctl;
          ls_code = ubp->ub_buffer[0];
  
*** 8564,8574 ****
                  return;
          }
  
          /* Process RSCN */
          if (sp->flags & SRB_UB_RSCN) {
!                 int sendup = 1;
  
                  /*
                   * Defer RSCN posting until commands return
                   */
                  QL_UB_UNLOCK(ha);
--- 8973,8983 ----
                  return;
          }
  
          /* Process RSCN */
          if (sp->flags & SRB_UB_RSCN) {
!                 int sendup;
  
                  /*
                   * Defer RSCN posting until commands return
                   */
                  QL_UB_UNLOCK(ha);
*** 8578,8598 ****
                  /* Abort outstanding commands */
                  sendup = ql_process_rscn(ha, af);
                  if (sendup == 0) {
  
                          TASK_DAEMON_LOCK(ha);
!                         ql_add_link_b(&pha->callback_queue, &sp->cmd);
                          TASK_DAEMON_UNLOCK(ha);
  
                          /*
                           * Wait for commands to drain in F/W (doesn't take
                           * more than a few milliseconds)
                           */
                          ql_delay(ha, 10000);
  
!                         QL_PRINT_2(CE_CONT, "(%d,%d): done rscn_sendup=0, "
!                             "fmt=%xh, d_id=%xh\n", ha->instance, ha->vp_index,
                              af->aff_format, af->aff_d_id);
                          return;
                  }
  
                  QL_UB_LOCK(ha);
--- 8987,9007 ----
                  /* Abort outstanding commands */
                  sendup = ql_process_rscn(ha, af);
                  if (sendup == 0) {
  
                          TASK_DAEMON_LOCK(ha);
!                         ql_add_link_b(&pha->unsol_callback_queue, &sp->cmd);
                          TASK_DAEMON_UNLOCK(ha);
  
                          /*
                           * Wait for commands to drain in F/W (doesn't take
                           * more than a few milliseconds)
                           */
                          ql_delay(ha, 10000);
  
!                         QL_PRINT_2(ha, "done rscn_sendup=0, "
!                             "fmt=%xh, d_id=%xh\n",
                              af->aff_format, af->aff_d_id);
                          return;
                  }
  
                  QL_UB_LOCK(ha);
*** 8605,8626 ****
          if ((r_ctl == R_CTL_ELS_REQ) && (ls_code == LA_ELS_LOGO)) {
                  QL_UB_UNLOCK(ha);
  
                  if (tq && (ql_process_logo_for_device(ha, tq) == 0)) {
                          TASK_DAEMON_LOCK(ha);
!                         ql_add_link_b(&pha->callback_queue, &sp->cmd);
                          TASK_DAEMON_UNLOCK(ha);
!                         QL_PRINT_2(CE_CONT, "(%d,%d): logo_sendup=0, d_id=%xh"
!                             "\n", ha->instance, ha->vp_index, tq->d_id.b24);
                          return;
                  }
  
                  QL_UB_LOCK(ha);
                  EL(ha, "sending unsol logout for %xh to transport\n",
                      ubp->ub_frame.s_id);
          }
  
          sp->flags &= ~(SRB_UB_IN_FCA | SRB_UB_IN_ISP | SRB_UB_RSCN |
              SRB_UB_FCP);
  
          if (sp->ub_type == FC_TYPE_IS8802_SNAP) {
                  (void) ddi_dma_sync(sp->ub_buffer.dma_handle, 0,
--- 9014,9040 ----
          if ((r_ctl == R_CTL_ELS_REQ) && (ls_code == LA_ELS_LOGO)) {
                  QL_UB_UNLOCK(ha);
  
                  if (tq && (ql_process_logo_for_device(ha, tq) == 0)) {
                          TASK_DAEMON_LOCK(ha);
!                         ql_add_link_b(&pha->unsol_callback_queue, &sp->cmd);
                          TASK_DAEMON_UNLOCK(ha);
!                         QL_PRINT_2(ha, "logo_sendup=0, d_id=%xh"
!                             "\n", tq->d_id.b24);
                          return;
                  }
  
                  QL_UB_LOCK(ha);
                  EL(ha, "sending unsol logout for %xh to transport\n",
                      ubp->ub_frame.s_id);
          }
  
+         if ((r_ctl == R_CTL_ELS_REQ) && (ls_code == LA_ELS_PLOGI)) {
+                 EL(ha, "sending unsol plogi for %xh to transport\n",
+                     ubp->ub_frame.s_id);
+         }
+ 
          sp->flags &= ~(SRB_UB_IN_FCA | SRB_UB_IN_ISP | SRB_UB_RSCN |
              SRB_UB_FCP);
  
          if (sp->ub_type == FC_TYPE_IS8802_SNAP) {
                  (void) ddi_dma_sync(sp->ub_buffer.dma_handle, 0,
*** 8629,8639 ****
          QL_UB_UNLOCK(ha);
  
          (ha->bind_info.port_unsol_cb)(ha->bind_info.port_handle,
              ubp, sp->ub_type);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_send_logo
   *
--- 9043,9053 ----
          QL_UB_UNLOCK(ha);
  
          (ha->bind_info.port_unsol_cb)(ha->bind_info.port_handle,
              ubp, sp->ub_type);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_send_logo
   *
*** 8651,8664 ****
          fc_unsol_buf_t          *ubp;
          ql_srb_t                *sp;
          la_els_logo_t           *payload;
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, d_id=%xh\n", ha->instance,
!             tq->d_id.b24);
  
!         if ((tq->d_id.b24 == 0) || (tq->d_id.b24 == 0xffffff)) {
                  EL(ha, "no device, d_id=%xh\n", tq->d_id.b24);
                  return;
          }
  
          if ((tq->flags & (TQF_RSCN_RCVD | TQF_PLOGI_PROGRS)) == 0 &&
--- 9065,9077 ----
          fc_unsol_buf_t          *ubp;
          ql_srb_t                *sp;
          la_els_logo_t           *payload;
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(ha, "started, d_id=%xh\n", tq->d_id.b24);
  
!         if ((tq->d_id.b24 == 0) || (tq->d_id.b24 == FS_BROADCAST)) {
                  EL(ha, "no device, d_id=%xh\n", tq->d_id.b24);
                  return;
          }
  
          if ((tq->flags & (TQF_RSCN_RCVD | TQF_PLOGI_PROGRS)) == 0 &&
*** 8674,8685 ****
                  DEVICE_QUEUE_LOCK(tq);
                  tq->flags |= TQF_NEED_AUTHENTICATION;
                  tq->logout_sent++;
                  DEVICE_QUEUE_UNLOCK(tq);
  
-                 EL(vha, "Received LOGO from = %xh\n", tq->d_id.b24);
- 
                  sp = ubp->ub_fca_private;
  
                  /* Set header. */
                  ubp->ub_frame.d_id = vha->d_id.b24;
                  ubp->ub_frame.r_ctl = R_CTL_ELS_REQ;
--- 9087,9096 ----
*** 8719,8729 ****
                  } else {
                          ql_awaken_task_daemon(ha, sp, 0, 0);
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  static int
  ql_process_logo_for_device(ql_adapter_state_t *ha, ql_tgt_t *tq)
  {
--- 9130,9140 ----
                  } else {
                          ql_awaken_task_daemon(ha, sp, 0, 0);
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  static int
  ql_process_logo_for_device(ql_adapter_state_t *ha, ql_tgt_t *tq)
  {
*** 8730,8740 ****
          port_id_t       d_id;
          ql_srb_t        *sp;
          ql_link_t       *link;
          int             sendup = 1;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          DEVICE_QUEUE_LOCK(tq);
          if (tq->outcnt) {
                  DEVICE_QUEUE_UNLOCK(tq);
                  sendup = 0;
--- 9141,9151 ----
          port_id_t       d_id;
          ql_srb_t        *sp;
          ql_link_t       *link;
          int             sendup = 1;
  
!         QL_PRINT_3(ha, "started\n");
  
          DEVICE_QUEUE_LOCK(tq);
          if (tq->outcnt) {
                  DEVICE_QUEUE_UNLOCK(tq);
                  sendup = 0;
*** 8742,8752 ****
                  ql_delay(ha, 10000);
          } else {
                  DEVICE_QUEUE_UNLOCK(tq);
                  TASK_DAEMON_LOCK(ha);
  
!                 for (link = ha->pha->callback_queue.first; link != NULL;
                      link = link->next) {
                          sp = link->base_address;
                          if (sp->flags & SRB_UB_CALLBACK) {
                                  continue;
                          }
--- 9153,9163 ----
                  ql_delay(ha, 10000);
          } else {
                  DEVICE_QUEUE_UNLOCK(tq);
                  TASK_DAEMON_LOCK(ha);
  
!                 for (link = ha->pha->unsol_callback_queue.first; link != NULL;
                      link = link->next) {
                          sp = link->base_address;
                          if (sp->flags & SRB_UB_CALLBACK) {
                                  continue;
                          }
*** 8759,8769 ****
                  }
  
                  TASK_DAEMON_UNLOCK(ha);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (sendup);
  }
  
  static int
--- 9170,9180 ----
                  }
  
                  TASK_DAEMON_UNLOCK(ha);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (sendup);
  }
  
  static int
*** 8772,8782 ****
          fc_unsol_buf_t          *ubp;
          ql_srb_t                *sp;
          la_els_logi_t           *payload;
          class_svc_param_t       *class3_param;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if ((tq->flags & TQF_RSCN_RCVD) || (ha->task_daemon_flags &
              LOOP_DOWN)) {
                  EL(ha, "Failed, tqf=%xh\n", tq->flags);
                  return (QL_FUNCTION_FAILED);
--- 9183,9193 ----
          fc_unsol_buf_t          *ubp;
          ql_srb_t                *sp;
          la_els_logi_t           *payload;
          class_svc_param_t       *class3_param;
  
!         QL_PRINT_3(ha, "started\n");
  
          if ((tq->flags & TQF_RSCN_RCVD) || (ha->task_daemon_flags &
              LOOP_DOWN)) {
                  EL(ha, "Failed, tqf=%xh\n", tq->flags);
                  return (QL_FUNCTION_FAILED);
*** 8787,8798 ****
          if (ubp == NULL) {
                  EL(ha, "Failed\n");
                  return (QL_FUNCTION_FAILED);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): Received LOGO from = %xh\n",
!             ha->instance, tq->d_id.b24);
  
          EL(ha, "Emulate PLOGI from = %xh tq = %x\n", tq->d_id.b24, tq);
  
          sp = ubp->ub_fca_private;
  
--- 9198,9208 ----
          if (ubp == NULL) {
                  EL(ha, "Failed\n");
                  return (QL_FUNCTION_FAILED);
          }
  
!         QL_PRINT_3(ha, "Received LOGO from = %xh\n", tq->d_id.b24);
  
          EL(ha, "Emulate PLOGI from = %xh tq = %x\n", tq->d_id.b24, tq);
  
          sp = ubp->ub_fca_private;
  
*** 8810,8833 ****
          ubp->ub_frame.rx_id = 0xffff;
          ubp->ub_frame.ox_id = 0xffff;
  
          /* set payload. */
          payload = (la_els_logi_t *)ubp->ub_buffer;
!         bzero(payload, sizeof (payload));
  
          payload->ls_code.ls_code = LA_ELS_PLOGI;
          payload->common_service.fcph_version = 0x2006;
!         payload->common_service.cmn_features = 0x8800;
! 
!         CFG_IST(ha, CFG_CTRL_24258081) ?
!             (payload->common_service.rx_bufsize = CHAR_TO_SHORT(
!             ha->init_ctrl_blk.cb24.max_frame_length[0],
!             ha->init_ctrl_blk.cb24.max_frame_length[1])) :
!             (payload->common_service.rx_bufsize = CHAR_TO_SHORT(
!             ha->init_ctrl_blk.cb.max_frame_length[0],
!             ha->init_ctrl_blk.cb.max_frame_length[1]));
! 
          payload->common_service.conc_sequences = 0xff;
          payload->common_service.relative_offset = 0x03;
          payload->common_service.e_d_tov = 0x7d0;
  
          bcopy((void *)&tq->port_name[0],
--- 9220,9237 ----
          ubp->ub_frame.rx_id = 0xffff;
          ubp->ub_frame.ox_id = 0xffff;
  
          /* set payload. */
          payload = (la_els_logi_t *)ubp->ub_buffer;
!         bzero(payload, sizeof (la_els_logi_t));
  
          payload->ls_code.ls_code = LA_ELS_PLOGI;
          payload->common_service.fcph_version = 0x2006;
!         payload->common_service.cmn_features =
!             ha->topology & QL_N_PORT ? 0x8000 : 0x8800;
!         payload->common_service.rx_bufsize =
!             ha->loginparams.common_service.rx_bufsize;
          payload->common_service.conc_sequences = 0xff;
          payload->common_service.relative_offset = 0x03;
          payload->common_service.e_d_tov = 0x7d0;
  
          bcopy((void *)&tq->port_name[0],
*** 8846,8864 ****
  
          QL_UB_LOCK(ha);
          sp->flags |= SRB_UB_CALLBACK;
          QL_UB_UNLOCK(ha);
  
-         ql_isp_els_handle_endian(ha, (uint8_t *)payload, LA_ELS_PLOGI);
- 
          if (done_q) {
                  ql_add_link_b(done_q, &sp->cmd);
          } else {
                  ql_awaken_task_daemon(ha, sp, 0, 0);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (QL_SUCCESS);
  }
  
  /*
--- 9250,9266 ----
  
          QL_UB_LOCK(ha);
          sp->flags |= SRB_UB_CALLBACK;
          QL_UB_UNLOCK(ha);
  
          if (done_q) {
                  ql_add_link_b(done_q, &sp->cmd);
          } else {
                  ql_awaken_task_daemon(ha, sp, 0, 0);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (QL_SUCCESS);
  }
  
  /*
*** 8873,8883 ****
          ql_lun_t        *lq;
          int             rval = QL_SUCCESS;
          ql_srb_t        *sp;
          ql_head_t       done_q = { NULL, NULL };
  
!         QL_PRINT_10(CE_CONT, "(%d,%d): started\n", ha->instance, ha->vp_index);
  
          /*
           * First clear, internally queued commands
           */
          DEVICE_QUEUE_LOCK(tq);
--- 9275,9285 ----
          ql_lun_t        *lq;
          int             rval = QL_SUCCESS;
          ql_srb_t        *sp;
          ql_head_t       done_q = { NULL, NULL };
  
!         QL_PRINT_10(ha, "started\n");
  
          /*
           * First clear, internally queued commands
           */
          DEVICE_QUEUE_LOCK(tq);
*** 8887,8900 ****
                  link2 = lq->cmd.first;
                  while (link2 != NULL) {
                          sp = link2->base_address;
                          link2 = link2->next;
  
-                         if (sp->flags & SRB_ABORT) {
-                                 continue;
-                         }
- 
                          /* Remove srb from device command queue. */
                          ql_remove_link(&lq->cmd, &sp->cmd);
                          sp->flags &= ~SRB_IN_DEVICE_QUEUE;
  
                          /* Set ending status. */
--- 9289,9298 ----
*** 8905,8915 ****
                  }
          }
          DEVICE_QUEUE_UNLOCK(tq);
  
          if (done_q.first != NULL) {
!                 ql_done(done_q.first);
          }
  
          if (drain && VALID_TARGET_ID(ha, tq->loop_id) && PD_PORT_LOGIN(tq)) {
                  rval = ql_abort_target(ha, tq, 0);
          }
--- 9303,9313 ----
                  }
          }
          DEVICE_QUEUE_UNLOCK(tq);
  
          if (done_q.first != NULL) {
!                 ql_done(done_q.first, B_FALSE);
          }
  
          if (drain && VALID_TARGET_ID(ha, tq->loop_id) && PD_PORT_LOGIN(tq)) {
                  rval = ql_abort_target(ha, tq, 0);
          }
*** 8916,8927 ****
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_10(CE_CONT, "(%d,%d): done\n", ha->instance,
!                     ha->vp_index);
          }
  
          return (rval);
  }
  
--- 9314,9324 ----
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh, d_id=%xh\n", rval, tq->d_id.b24);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_10(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 8944,8954 ****
          ql_srb_t                *sp;
          fc_rscn_t               *rn;
          fc_affected_id_t        *af;
          port_id_t               d_id;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Locate a buffer to use. */
          ubp = ql_get_unsolicited_buffer(ha, FC_TYPE_EXTENDED_LS);
          if (ubp != NULL) {
                  sp = ubp->ub_fca_private;
--- 9341,9351 ----
          ql_srb_t                *sp;
          fc_rscn_t               *rn;
          fc_affected_id_t        *af;
          port_id_t               d_id;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Locate a buffer to use. */
          ubp = ql_get_unsolicited_buffer(ha, FC_TYPE_EXTENDED_LS);
          if (ubp != NULL) {
                  sp = ubp->ub_fca_private;
*** 8993,9003 ****
  
          if (ubp == NULL) {
                  EL(ha, "Failed, get_unsolicited_buffer\n");
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  }
  
  /*
   * ql_update_rscn
--- 9390,9400 ----
  
          if (ubp == NULL) {
                  EL(ha, "Failed, get_unsolicited_buffer\n");
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  }
  
  /*
   * ql_update_rscn
*** 9015,9025 ****
  {
          ql_link_t       *link;
          uint16_t        index;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (af->aff_format == FC_RSCN_PORT_ADDRESS) {
                  port_id_t d_id;
  
                  d_id.r.rsvd_1 = 0;
--- 9412,9422 ----
  {
          ql_link_t       *link;
          uint16_t        index;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (af->aff_format == FC_RSCN_PORT_ADDRESS) {
                  port_id_t d_id;
  
                  d_id.r.rsvd_1 = 0;
*** 9028,9041 ****
                  tq = ql_d_id_to_queue(ha, d_id);
                  if (tq) {
                          EL(ha, "SD_RSCN_RCVD %xh RPA\n", d_id.b24);
                          DEVICE_QUEUE_LOCK(tq);
                          tq->flags |= TQF_RSCN_RCVD;
                          DEVICE_QUEUE_UNLOCK(tq);
                  }
!                 QL_PRINT_3(CE_CONT, "(%d): FC_RSCN_PORT_ADDRESS done\n",
!                     ha->instance);
  
                  return;
          }
  
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
--- 9425,9438 ----
                  tq = ql_d_id_to_queue(ha, d_id);
                  if (tq) {
                          EL(ha, "SD_RSCN_RCVD %xh RPA\n", d_id.b24);
                          DEVICE_QUEUE_LOCK(tq);
                          tq->flags |= TQF_RSCN_RCVD;
+                         ql_requeue_pending_cmds(ha, tq);
                          DEVICE_QUEUE_UNLOCK(tq);
                  }
!                 QL_PRINT_3(ha, "FC_RSCN_PORT_ADDRESS done\n");
  
                  return;
          }
  
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
*** 9048,9057 ****
--- 9445,9455 ----
                                  if (!RESERVED_LOOP_ID(ha, tq->loop_id)) {
                                          EL(ha, "SD_RSCN_RCVD %xh RFA\n",
                                              tq->d_id.b24);
                                          DEVICE_QUEUE_LOCK(tq);
                                          tq->flags |= TQF_RSCN_RCVD;
+                                         ql_requeue_pending_cmds(ha, tq);
                                          DEVICE_QUEUE_UNLOCK(tq);
                                  }
                                  break;
  
                          case FC_RSCN_AREA_ADDRESS:
*** 9058,9067 ****
--- 9456,9466 ----
                                  if ((tq->d_id.b24 & 0xffff00) == af->aff_d_id) {
                                          EL(ha, "SD_RSCN_RCVD %xh RAA\n",
                                              tq->d_id.b24);
                                          DEVICE_QUEUE_LOCK(tq);
                                          tq->flags |= TQF_RSCN_RCVD;
+                                         ql_requeue_pending_cmds(ha, tq);
                                          DEVICE_QUEUE_UNLOCK(tq);
                                  }
                                  break;
  
                          case FC_RSCN_DOMAIN_ADDRESS:
*** 9068,9090 ****
                                  if ((tq->d_id.b24 & 0xff0000) == af->aff_d_id) {
                                          EL(ha, "SD_RSCN_RCVD %xh RDA\n",
                                              tq->d_id.b24);
                                          DEVICE_QUEUE_LOCK(tq);
                                          tq->flags |= TQF_RSCN_RCVD;
                                          DEVICE_QUEUE_UNLOCK(tq);
                                  }
                                  break;
  
                          default:
                                  break;
                          }
                  }
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_process_rscn
   *
   * Input:
   *      ha:     adapter state pointer.
   *      af:     RSCN payload pointer.
--- 9467,9540 ----
                                  if ((tq->d_id.b24 & 0xff0000) == af->aff_d_id) {
                                          EL(ha, "SD_RSCN_RCVD %xh RDA\n",
                                              tq->d_id.b24);
                                          DEVICE_QUEUE_LOCK(tq);
                                          tq->flags |= TQF_RSCN_RCVD;
+                                         ql_requeue_pending_cmds(ha, tq);
                                          DEVICE_QUEUE_UNLOCK(tq);
                                  }
                                  break;
  
                          default:
                                  break;
                          }
                  }
          }
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
+  * ql_requeue_pending_cmds
+  *      Requeue target commands from pending queue to LUN queue
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *      tq:     target queue pointer.
+  *      DEVICE_QUEUE_LOCK must be already obtained.
+  *
+  * Context:
+  *      Interrupt or Kernel context, no mailbox commands allowed.
+  */
+ void
+ ql_requeue_pending_cmds(ql_adapter_state_t *vha, ql_tgt_t *tq)
+ {
+         ql_link_t               *link;
+         ql_srb_t                *sp;
+         ql_lun_t                *lq;
+         ql_adapter_state_t      *ha = vha->pha;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         REQUEST_RING_LOCK(ha);
+         for (link = ha->pending_cmds.first; link != NULL; link = link->next) {
+                 sp = link->base_address;
+                 if ((lq = sp->lun_queue) == NULL || lq->target_queue != tq) {
+                         continue;
+                 }
+                 ql_remove_link(&ha->pending_cmds, &sp->cmd);
+ 
+                 if (tq->outcnt) {
+                         tq->outcnt--;
+                 }
+                 if (sp->flags & SRB_FCP_CMD_PKT) {
+                         if (sp->fcp->fcp_cntl.cntl_qtype ==
+                             FCP_QTYPE_UNTAGGED) {
+                                 lq->flags &= ~LQF_UNTAGGED_PENDING;
+                         }
+                         if (lq->lun_outcnt != 0) {
+                                 lq->lun_outcnt--;
+                         }
+                 }
+                 ql_add_link_t(&lq->cmd, &sp->cmd);
+                 sp->flags |= SRB_IN_DEVICE_QUEUE;
+         }
+         REQUEST_RING_UNLOCK(ha);
+ 
+         QL_PRINT_3(ha, "done\n");
+ }
+ 
+ /*
   * ql_process_rscn
   *
   * Input:
   *      ha:     adapter state pointer.
   *      af:     RSCN payload pointer.
*** 9099,9109 ****
          int             sendup = 1;
          ql_link_t       *link;
          uint16_t        index;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (af->aff_format == FC_RSCN_PORT_ADDRESS) {
                  port_id_t d_id;
  
                  d_id.r.rsvd_1 = 0;
--- 9549,9559 ----
          int             sendup = 1;
          ql_link_t       *link;
          uint16_t        index;
          ql_tgt_t        *tq;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (af->aff_format == FC_RSCN_PORT_ADDRESS) {
                  port_id_t d_id;
  
                  d_id.r.rsvd_1 = 0;
*** 9112,9122 ****
                  tq = ql_d_id_to_queue(ha, d_id);
                  if (tq) {
                          sendup = ql_process_rscn_for_device(ha, tq);
                  }
  
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
                  return (sendup);
          }
  
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
--- 9562,9572 ----
                  tq = ql_d_id_to_queue(ha, d_id);
                  if (tq) {
                          sendup = ql_process_rscn_for_device(ha, tq);
                  }
  
!                 QL_PRINT_3(ha, "done\n");
  
                  return (sendup);
          }
  
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
*** 9167,9177 ****
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (sendup);
  }
  
  /*
--- 9617,9627 ----
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (sendup);
  }
  
  /*
*** 9187,9197 ****
  static int
  ql_process_rscn_for_device(ql_adapter_state_t *ha, ql_tgt_t *tq)
  {
          int sendup = 1;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          DEVICE_QUEUE_LOCK(tq);
  
          /*
           * Let FCP-2 compliant devices continue I/Os
--- 9637,9647 ----
  static int
  ql_process_rscn_for_device(ql_adapter_state_t *ha, ql_tgt_t *tq)
  {
          int sendup = 1;
  
!         QL_PRINT_3(ha, "started\n");
  
          DEVICE_QUEUE_LOCK(tq);
  
          /*
           * Let FCP-2 compliant devices continue I/Os
*** 9219,9228 ****
--- 9669,9679 ----
                  (void) ql_abort_device(ha, tq, 1);
  
                  DEVICE_QUEUE_LOCK(tq);
  
                  if (tq->outcnt) {
+                         EL(ha, "busy tq->outcnt=%d\n", tq->outcnt);
                          sendup = 0;
                  } else {
                          tq->flags &= ~TQF_RSCN_RCVD;
                  }
          } else {
*** 9235,9245 ****
                  }
          }
  
          DEVICE_QUEUE_UNLOCK(tq);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (sendup);
  }
  
  static int
--- 9686,9696 ----
                  }
          }
  
          DEVICE_QUEUE_UNLOCK(tq);
  
!         QL_PRINT_3(ha, "done\n");
  
          return (sendup);
  }
  
  static int
*** 9252,9262 ****
          uint32_t                list_size;
          port_id_t               d_id;
          ql_mbx_data_t           mr;
          ql_head_t               done_q = { NULL, NULL };
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
          list = kmem_zalloc(list_size, KM_SLEEP);
          if (list == NULL) {
                  rval = QL_MEMORY_ALLOC_FAILED;
--- 9703,9713 ----
          uint32_t                list_size;
          port_id_t               d_id;
          ql_mbx_data_t           mr;
          ql_head_t               done_q = { NULL, NULL };
  
!         QL_PRINT_3(ha, "started\n");
  
          list_size = sizeof (ql_dev_id_list_t) * DEVICE_LIST_ENTRIES;
          list = kmem_zalloc(list_size, KM_SLEEP);
          if (list == NULL) {
                  rval = QL_MEMORY_ALLOC_FAILED;
*** 9290,9300 ****
                          }
  
                          tq = ql_dev_init(ha, d_id, loop_id);
  
                          /* Test for fabric device. */
!                         if (d_id.b.domain != ha->d_id.b.domain ||
                              d_id.b.area != ha->d_id.b.area) {
                                  tq->flags |= TQF_FABRIC_DEVICE;
                          }
  
                          ADAPTER_STATE_UNLOCK(ha);
--- 9741,9752 ----
                          }
  
                          tq = ql_dev_init(ha, d_id, loop_id);
  
                          /* Test for fabric device. */
!                         if (ha->topology & QL_F_PORT ||
!                             d_id.b.domain != ha->d_id.b.domain ||
                              d_id.b.area != ha->d_id.b.area) {
                                  tq->flags |= TQF_FABRIC_DEVICE;
                          }
  
                          ADAPTER_STATE_UNLOCK(ha);
*** 9315,9334 ****
  
          /* Release adapter state lock. */
          ADAPTER_STATE_UNLOCK(ha);
  
          if (done_q.first != NULL) {
!                 ql_done(done_q.first);
          }
  
          kmem_free(list, list_size);
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  
          return (rval);
  }
  
--- 9767,9786 ----
  
          /* Release adapter state lock. */
          ADAPTER_STATE_UNLOCK(ha);
  
          if (done_q.first != NULL) {
!                 ql_done(done_q.first, B_FALSE);
          }
  
          kmem_free(list, list_size);
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 9348,9366 ****
  ql_free_unsolicited_buffer(ql_adapter_state_t *ha, fc_unsol_buf_t *ubp)
  {
          ql_srb_t        *sp;
          int             status;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          sp = ubp->ub_fca_private;
          if (sp->ub_type == FC_TYPE_IS8802_SNAP) {
                  /* Disconnect IP from system buffers. */
                  if (ha->flags & IP_INITIALIZED) {
-                         ADAPTER_STATE_UNLOCK(ha);
                          status = ql_shutdown_ip(ha);
-                         ADAPTER_STATE_LOCK(ha);
                          if (status != QL_SUCCESS) {
                                  cmn_err(CE_WARN,
                                      "!Qlogic %s(%d): Failed to shutdown IP",
                                      QL_NAME, ha->instance);
                                  return;
--- 9800,9816 ----
  ql_free_unsolicited_buffer(ql_adapter_state_t *ha, fc_unsol_buf_t *ubp)
  {
          ql_srb_t        *sp;
          int             status;
  
!         QL_PRINT_3(ha, "started\n");
  
          sp = ubp->ub_fca_private;
          if (sp->ub_type == FC_TYPE_IS8802_SNAP) {
                  /* Disconnect IP from system buffers. */
                  if (ha->flags & IP_INITIALIZED) {
                          status = ql_shutdown_ip(ha);
                          if (status != QL_SUCCESS) {
                                  cmn_err(CE_WARN,
                                      "!Qlogic %s(%d): Failed to shutdown IP",
                                      QL_NAME, ha->instance);
                                  return;
*** 9375,9389 ****
          }
  
          kmem_free(sp, sizeof (ql_srb_t));
          kmem_free(ubp, sizeof (fc_unsol_buf_t));
  
          if (ha->ub_allocated != 0) {
                  ha->ub_allocated--;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_get_unsolicited_buffer
   *      Locates a free unsolicited buffer.
--- 9825,9841 ----
          }
  
          kmem_free(sp, sizeof (ql_srb_t));
          kmem_free(ubp, sizeof (fc_unsol_buf_t));
  
+         QL_UB_LOCK(ha);
          if (ha->ub_allocated != 0) {
                  ha->ub_allocated--;
          }
+         QL_UB_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_get_unsolicited_buffer
   *      Locates a free unsolicited buffer.
*** 9403,9413 ****
  {
          fc_unsol_buf_t  *ubp;
          ql_srb_t        *sp;
          uint16_t        index;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Locate a buffer to use. */
          ubp = NULL;
  
          QL_UB_LOCK(ha);
--- 9855,9865 ----
  {
          fc_unsol_buf_t  *ubp;
          ql_srb_t        *sp;
          uint16_t        index;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Locate a buffer to use. */
          ubp = NULL;
  
          QL_UB_LOCK(ha);
*** 9431,9441 ****
          if (ubp) {
                  ubp->ub_resp_token = NULL;
                  ubp->ub_class = FC_TRAN_CLASS3;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (ubp);
  }
  
  /*
--- 9883,9893 ----
          if (ubp) {
                  ubp->ub_resp_token = NULL;
                  ubp->ub_class = FC_TRAN_CLASS3;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (ubp);
  }
  
  /*
*** 9461,9471 ****
          fc_unsol_buf_t  *ubp;
          ql_srb_t        *sp;
          uint16_t        loop_id;
          int             rval = QL_FUNCTION_FAILED;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          QL_UB_LOCK(ha);
          if (index >= QL_UB_LIMIT || (ubp = ha->ub_array[index]) == NULL) {
                  EL(ha, "Invalid buffer index=%xh\n", index);
                  QL_UB_UNLOCK(ha);
--- 9913,9923 ----
          fc_unsol_buf_t  *ubp;
          ql_srb_t        *sp;
          uint16_t        loop_id;
          int             rval = QL_FUNCTION_FAILED;
  
!         QL_PRINT_3(ha, "started\n");
  
          QL_UB_LOCK(ha);
          if (index >= QL_UB_LIMIT || (ubp = ha->ub_array[index]) == NULL) {
                  EL(ha, "Invalid buffer index=%xh\n", index);
                  QL_UB_UNLOCK(ha);
*** 9487,9503 ****
          if ((sp->handle == index) &&
              (sp->flags & SRB_UB_IN_ISP) &&
              (sp->ub_type == FC_TYPE_IS8802_SNAP) &&
              (!(sp->flags & SRB_UB_ACQUIRED))) {
                  /* set broadcast D_ID */
!                 loop_id = (uint16_t)(CFG_IST(ha, CFG_CTRL_24258081) ?
                      BROADCAST_24XX_HDL : IP_BROADCAST_LOOP_ID);
                  if (tq->ub_loop_id == loop_id) {
                          if (ha->topology & QL_FL_PORT) {
                                  ubp->ub_frame.d_id = 0x000000;
                          } else {
!                                 ubp->ub_frame.d_id = 0xffffff;
                          }
                  } else {
                          ubp->ub_frame.d_id = ha->d_id.b24;
                  }
                  ubp->ub_frame.r_ctl = R_CTL_UNSOL_DATA;
--- 9939,9955 ----
          if ((sp->handle == index) &&
              (sp->flags & SRB_UB_IN_ISP) &&
              (sp->ub_type == FC_TYPE_IS8802_SNAP) &&
              (!(sp->flags & SRB_UB_ACQUIRED))) {
                  /* set broadcast D_ID */
!                 loop_id = (uint16_t)(CFG_IST(ha, CFG_ISP_FW_TYPE_2) ?
                      BROADCAST_24XX_HDL : IP_BROADCAST_LOOP_ID);
                  if (tq->ub_loop_id == loop_id) {
                          if (ha->topology & QL_FL_PORT) {
                                  ubp->ub_frame.d_id = 0x000000;
                          } else {
!                                 ubp->ub_frame.d_id = FS_BROADCAST;
                          }
                  } else {
                          ubp->ub_frame.d_id = ha->d_id.b24;
                  }
                  ubp->ub_frame.r_ctl = R_CTL_UNSOL_DATA;
*** 9531,9554 ****
                          ubp->ub_frame.f_ctl = F_CTL_RO_PRESENT |
                              F_CTL_FIRST_SEQ;
                          ubp->ub_frame.df_ctl = 0x20;
                  }
  
!                 QL_PRINT_3(CE_CONT, "(%d): ub_frame.d_id=%xh\n",
!                     ha->instance, ubp->ub_frame.d_id);
!                 QL_PRINT_3(CE_CONT, "(%d): ub_frame.s_id=%xh\n",
!                     ha->instance, ubp->ub_frame.s_id);
!                 QL_PRINT_3(CE_CONT, "(%d): ub_frame.seq_cnt=%xh\n",
!                     ha->instance, ubp->ub_frame.seq_cnt);
!                 QL_PRINT_3(CE_CONT, "(%d): ub_frame.seq_id=%xh\n",
!                     ha->instance, ubp->ub_frame.seq_id);
!                 QL_PRINT_3(CE_CONT, "(%d): ub_frame.ro=%xh\n",
!                     ha->instance, ubp->ub_frame.ro);
!                 QL_PRINT_3(CE_CONT, "(%d): ub_frame.f_ctl=%xh\n",
!                     ha->instance, ubp->ub_frame.f_ctl);
!                 QL_PRINT_3(CE_CONT, "(%d): ub_bufsize=%xh\n",
!                     ha->instance, ubp->ub_bufsize);
                  QL_DUMP_3(ubp->ub_buffer, 8,
                      ubp->ub_bufsize < 64 ? ubp->ub_bufsize : 64);
  
                  sp->flags |= SRB_UB_CALLBACK | SRB_UB_ACQUIRED;
                  ql_add_link_b(done_q, &sp->cmd);
--- 9983,9999 ----
                          ubp->ub_frame.f_ctl = F_CTL_RO_PRESENT |
                              F_CTL_FIRST_SEQ;
                          ubp->ub_frame.df_ctl = 0x20;
                  }
  
!                 QL_PRINT_3(ha, "ub_frame.d_id=%xh\n", ubp->ub_frame.d_id);
!                 QL_PRINT_3(ha, "ub_frame.s_id=%xh\n", ubp->ub_frame.s_id);
!                 QL_PRINT_3(ha, "ub_frame.seq_cnt=%xh\n", ubp->ub_frame.seq_cnt);
!                 QL_PRINT_3(ha, "ub_frame.seq_id=%xh\n", ubp->ub_frame.seq_id);
!                 QL_PRINT_3(ha, "ub_frame.ro=%xh\n", ubp->ub_frame.ro);
!                 QL_PRINT_3(ha, "ub_frame.f_ctl=%xh\n", ubp->ub_frame.f_ctl);
!                 QL_PRINT_3(ha, "ub_bufsize=%xh\n", ubp->ub_bufsize);
                  QL_DUMP_3(ubp->ub_buffer, 8,
                      ubp->ub_bufsize < 64 ? ubp->ub_bufsize : 64);
  
                  sp->flags |= SRB_UB_CALLBACK | SRB_UB_ACQUIRED;
                  ql_add_link_b(done_q, &sp->cmd);
*** 9571,9581 ****
                              index);
                  }
          }
          QL_UB_UNLOCK(ha);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 10016,10026 ----
                              index);
                  }
          }
          QL_UB_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 9590,9641 ****
   */
  static void
  ql_timer(void *arg)
  {
          ql_link_t               *link;
!         uint32_t                set_flags;
!         uint32_t                reset_flags;
!         ql_adapter_state_t      *ha = NULL, *vha;
  
!         QL_PRINT_6(CE_CONT, "started\n");
  
          /* Acquire global state lock. */
!         GLOBAL_STATE_LOCK();
          if (ql_timer_timeout_id == NULL) {
                  /* Release global state lock. */
!                 GLOBAL_STATE_UNLOCK();
                  return;
          }
  
          for (link = ql_hba.first; link != NULL; link = link->next) {
                  ha = link->base_address;
  
!                 /* Skip adapter if suspended of stalled. */
!                 ADAPTER_STATE_LOCK(ha);
                  if (ha->flags & ADAPTER_SUSPENDED ||
!                     ha->task_daemon_flags & DRIVER_STALL) {
!                         ADAPTER_STATE_UNLOCK(ha);
                          continue;
                  }
-                 ha->flags |= ADAPTER_TIMER_BUSY;
-                 ADAPTER_STATE_UNLOCK(ha);
  
                  QL_PM_LOCK(ha);
                  if (ha->power_level != PM_LEVEL_D0) {
                          QL_PM_UNLOCK(ha);
- 
-                         ADAPTER_STATE_LOCK(ha);
-                         ha->flags &= ~ADAPTER_TIMER_BUSY;
-                         ADAPTER_STATE_UNLOCK(ha);
                          continue;
                  }
!                 ha->busy++;
                  QL_PM_UNLOCK(ha);
  
                  set_flags = 0;
-                 reset_flags = 0;
  
                  /* Port retry timer handler. */
                  if (LOOP_READY(ha)) {
                          ADAPTER_STATE_LOCK(ha);
                          if (ha->port_retry_timer != 0) {
                                  ha->port_retry_timer--;
--- 10035,10086 ----
   */
  static void
  ql_timer(void *arg)
  {
          ql_link_t               *link;
!         uint64_t                set_flags;
!         ql_adapter_state_t      *ha;
!         static uint32_t         sec_cnt = 0;
  
!         QL_PRINT_6(NULL, "started\n");
  
          /* Acquire global state lock. */
!         GLOBAL_TIMER_LOCK();
          if (ql_timer_timeout_id == NULL) {
                  /* Release global state lock. */
!                 GLOBAL_TIMER_UNLOCK();
                  return;
          }
  
+         sec_cnt++;
          for (link = ql_hba.first; link != NULL; link = link->next) {
                  ha = link->base_address;
  
!                 /* Skip adapter if suspended or stalled. */
                  if (ha->flags & ADAPTER_SUSPENDED ||
!                     ha->task_daemon_flags & DRIVER_STALL ||
!                     !(ha->task_daemon_flags & FIRMWARE_UP)) {
                          continue;
                  }
  
                  QL_PM_LOCK(ha);
                  if (ha->power_level != PM_LEVEL_D0) {
                          QL_PM_UNLOCK(ha);
                          continue;
                  }
!                 ha->pm_busy++;
                  QL_PM_UNLOCK(ha);
  
                  set_flags = 0;
  
+                 /* All completion treads busy, wake up a helper thread. */
+                 if (ha->comp_thds_awake == ha->comp_thds_active &&
+                     ha->comp_q.first != NULL) {
+                         QL_PRINT_10(ha, "comp queue helper thrd started\n");
+                         (void) timeout(ql_process_comp_queue, (void *)ha, 1);
+                 }
+ 
                  /* Port retry timer handler. */
                  if (LOOP_READY(ha)) {
                          ADAPTER_STATE_LOCK(ha);
                          if (ha->port_retry_timer != 0) {
                                  ha->port_retry_timer--;
*** 9655,9666 ****
                                   * a chance to work.
                                   */
                                  if (ha->loop_down_timer == LOOP_DOWN_RESET) {
                                          if (CFG_IST(ha,
                                              CFG_DUMP_LOOP_OFFLINE_TIMEOUT)) {
!                                                 (void) ql_binary_fw_dump(ha,
!                                                     TRUE);
                                          }
                                          EL(ha, "loop_down_reset, "
                                              "isp_abort_needed\n");
                                          set_flags |= ISP_ABORT_NEEDED;
                                  }
--- 10100,10112 ----
                                   * a chance to work.
                                   */
                                  if (ha->loop_down_timer == LOOP_DOWN_RESET) {
                                          if (CFG_IST(ha,
                                              CFG_DUMP_LOOP_OFFLINE_TIMEOUT)) {
!                                                 ADAPTER_STATE_LOCK(ha);
!                                                 ha->flags |= FW_DUMP_NEEDED;
!                                                 ADAPTER_STATE_UNLOCK(ha);
                                          }
                                          EL(ha, "loop_down_reset, "
                                              "isp_abort_needed\n");
                                          set_flags |= ISP_ABORT_NEEDED;
                                  }
*** 9681,9702 ****
                                  if (ha->watchdog_timer == 0) {
                                          ha->watchdog_timer = WATCHDOG_TIME;
                                  } else if (LOOP_READY(ha)) {
                                          ha->watchdog_timer--;
                                          if (ha->watchdog_timer == 0) {
!                                                 for (vha = ha; vha != NULL;
!                                                     vha = vha->vp_next) {
!                                                         ql_watchdog(vha,
!                                                             &set_flags,
!                                                             &reset_flags);
                                                  }
-                                                 ha->watchdog_timer =
-                                                     WATCHDOG_TIME;
                                          }
                                  }
                          }
-                 }
  
                  /* Idle timer handler. */
                  if (!DRIVER_SUSPENDED(ha)) {
                          if (++ha->idle_timer >= IDLE_CHECK_TIMER) {
  #if defined(QL_DEBUG_LEVEL_6) || !defined(QL_DEBUG_LEVEL_3)
--- 10127,10141 ----
                                  if (ha->watchdog_timer == 0) {
                                          ha->watchdog_timer = WATCHDOG_TIME;
                                  } else if (LOOP_READY(ha)) {
                                          ha->watchdog_timer--;
                                          if (ha->watchdog_timer == 0) {
!                                                 set_flags |= WATCHDOG_NEEDED;
                                          }
                                  }
                          }
                  }
  
                  /* Idle timer handler. */
                  if (!DRIVER_SUSPENDED(ha)) {
                          if (++ha->idle_timer >= IDLE_CHECK_TIMER) {
  #if defined(QL_DEBUG_LEVEL_6) || !defined(QL_DEBUG_LEVEL_3)
*** 9709,9746 ****
                                  if (ha->send_plogi_timer == NULL) {
                                          set_flags |= SEND_PLOGI;
                                  }
                          }
                  }
!                 ADAPTER_STATE_LOCK(ha);
!                 if (ha->idc_restart_timer != 0) {
!                         ha->idc_restart_timer--;
!                         if (ha->idc_restart_timer == 0) {
!                                 ha->idc_restart_cnt = 0;
!                                 reset_flags |= DRIVER_STALL;
                          }
-                 }
-                 if (ha->idc_flash_acc_timer != 0) {
-                         ha->idc_flash_acc_timer--;
-                         if (ha->idc_flash_acc_timer == 0 &&
-                             ha->idc_flash_acc != 0) {
-                                 ha->idc_flash_acc = 1;
-                                 ha->idc_mb[0] = MBA_IDC_NOTIFICATION;
-                                 ha->idc_mb[1] = 0;
-                                 ha->idc_mb[2] = IDC_OPC_DRV_START;
-                                 set_flags |= IDC_EVENT;
-                         }
-                 }
-                 ADAPTER_STATE_UNLOCK(ha);
  
!                 if (set_flags != 0 || reset_flags != 0) {
!                         ql_awaken_task_daemon(ha, NULL, set_flags,
!                             reset_flags);
                  }
  
!                 if (ha->xioctl->ledstate.BeaconState == BEACON_ON) {
!                         ql_blink_led(ha);
                  }
  
                  /* Update the IO stats */
                  if (ha->xioctl->IOInputByteCnt >= 0x100000) {
                          ha->xioctl->IOInputMByteCnt +=
--- 10148,10171 ----
                                  if (ha->send_plogi_timer == NULL) {
                                          set_flags |= SEND_PLOGI;
                                  }
                          }
                  }
! 
!                 if (CFG_IST(ha, CFG_CTRL_82XX) && ha->flags & ONLINE &&
!                     !(ha->task_daemon_flags & (ISP_ABORT_NEEDED |
!                     ABORT_ISP_ACTIVE)) &&
!                     !(sec_cnt % 2)) {
!                         set_flags |= IDC_POLL_NEEDED;
                  }
  
!                 if (ha->ledstate.BeaconState == BEACON_ON) {
!                         set_flags |= LED_BLINK;
                  }
  
!                 if (set_flags != 0) {
!                         ql_awaken_task_daemon(ha, NULL, set_flags, 0);
                  }
  
                  /* Update the IO stats */
                  if (ha->xioctl->IOInputByteCnt >= 0x100000) {
                          ha->xioctl->IOInputMByteCnt +=
*** 9752,9783 ****
                          ha->xioctl->IOOutputMByteCnt +=
                              (ha->xioctl->IOOutputByteCnt / 0x100000);
                          ha->xioctl->IOOutputByteCnt %= 0x100000;
                  }
  
-                 if (CFG_IST(ha, CFG_CTRL_8021)) {
-                         (void) ql_8021_idc_handler(ha);
-                 }
- 
-                 ADAPTER_STATE_LOCK(ha);
-                 ha->flags &= ~ADAPTER_TIMER_BUSY;
-                 ADAPTER_STATE_UNLOCK(ha);
- 
                  QL_PM_LOCK(ha);
!                 ha->busy--;
                  QL_PM_UNLOCK(ha);
          }
  
          /* Restart timer, if not being stopped. */
          if (ql_timer_timeout_id != NULL) {
                  ql_timer_timeout_id = timeout(ql_timer, arg, ql_timer_ticks);
          }
  
          /* Release global state lock. */
!         GLOBAL_STATE_UNLOCK();
  
!         QL_PRINT_6(CE_CONT, "done\n");
  }
  
  /*
   * ql_timeout_insert
   *      Function used to insert a command block onto the
--- 10177,10202 ----
                          ha->xioctl->IOOutputMByteCnt +=
                              (ha->xioctl->IOOutputByteCnt / 0x100000);
                          ha->xioctl->IOOutputByteCnt %= 0x100000;
                  }
  
                  QL_PM_LOCK(ha);
!                 if (ha->pm_busy) {
!                         ha->pm_busy--;
!                 }
                  QL_PM_UNLOCK(ha);
          }
  
          /* Restart timer, if not being stopped. */
          if (ql_timer_timeout_id != NULL) {
                  ql_timer_timeout_id = timeout(ql_timer, arg, ql_timer_ticks);
          }
  
          /* Release global state lock. */
!         GLOBAL_TIMER_UNLOCK();
  
!         QL_PRINT_6(ha, "done\n");
  }
  
  /*
   * ql_timeout_insert
   *      Function used to insert a command block onto the
*** 9797,9807 ****
   */
  /* ARGSUSED */
  static void
  ql_timeout_insert(ql_adapter_state_t *ha, ql_tgt_t *tq, ql_srb_t *sp)
  {
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (sp->pkt->pkt_timeout != 0 && sp->pkt->pkt_timeout < 0x10000) {
                  sp->isp_timeout = (uint16_t)(sp->pkt->pkt_timeout);
                  /*
                   * The WATCHDOG_TIME must be rounded up + 1.  As an example,
--- 10216,10226 ----
   */
  /* ARGSUSED */
  static void
  ql_timeout_insert(ql_adapter_state_t *ha, ql_tgt_t *tq, ql_srb_t *sp)
  {
!         QL_PRINT_3(ha, "started\n");
  
          if (sp->pkt->pkt_timeout != 0 && sp->pkt->pkt_timeout < 0x10000) {
                  sp->isp_timeout = (uint16_t)(sp->pkt->pkt_timeout);
                  /*
                   * The WATCHDOG_TIME must be rounded up + 1.  As an example,
*** 9836,9846 ****
                  sp->isp_timeout = 0;
                  sp->wdg_q_time = 0;
                  sp->init_wdg_q_time = 0;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_watchdog
   *      Timeout handler that runs in interrupt context. The
--- 10255,10265 ----
                  sp->isp_timeout = 0;
                  sp->wdg_q_time = 0;
                  sp->init_wdg_q_time = 0;
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_watchdog
   *      Timeout handler that runs in interrupt context. The
*** 9849,9923 ****
   *      Function used to update timeout values and if timeout
   *      has occurred command will be aborted.
   *
   * Input:
   *      ha:             adapter state pointer.
-  *      set_flags:      task daemon flags to set.
-  *      reset_flags:    task daemon flags to reset.
   *
   * Context:
!  *      Interrupt context, no mailbox commands allowed.
   */
  static void
! ql_watchdog(ql_adapter_state_t *ha, uint32_t *set_flags, uint32_t *reset_flags)
  {
-         ql_srb_t        *sp;
          ql_link_t       *link;
-         ql_link_t       *next_cmd;
-         ql_link_t       *next_device;
          ql_tgt_t        *tq;
-         ql_lun_t        *lq;
          uint16_t        index;
!         int             q_sane;
  
!         QL_PRINT_6(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Loop through all targets. */
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
!                 for (link = ha->dev[index].first; link != NULL;
!                     link = next_device) {
                          tq = link->base_address;
  
                          /* Try to acquire device queue lock. */
                          if (TRY_DEVICE_QUEUE_LOCK(tq) == 0) {
!                                 next_device = NULL;
!                                 continue;
                          }
  
!                         next_device = link->next;
! 
!                         if (!(CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) &&
                              (tq->port_down_retry_count == 0)) {
                                  /* Release device queue lock. */
                                  DEVICE_QUEUE_UNLOCK(tq);
                                  continue;
                          }
  
!                         /* Find out if this device is in a sane state. */
!                         if (tq->flags & (TQF_RSCN_RCVD |
!                             TQF_NEED_AUTHENTICATION | TQF_QUEUE_SUSPENDED)) {
!                                 q_sane = 0;
                          } else {
!                                 q_sane = 1;
                          }
                          /* Loop through commands on watchdog queue. */
!                         for (link = tq->wdg.first; link != NULL;
!                             link = next_cmd) {
                                  next_cmd = link->next;
                                  sp = link->base_address;
                                  lq = sp->lun_queue;
  
                                  /*
!                                  * For SCSI commands, if everything seems to
!                                  * be going fine and this packet is stuck
!                                  * because of throttling at LUN or target
!                                  * level then do not decrement the
!                                  * sp->wdg_q_time
                                   */
                                  if (ha->task_daemon_flags & STATE_ONLINE &&
!                                     (sp->flags & SRB_ISP_STARTED) == 0 &&
!                                     q_sane && sp->flags & SRB_FCP_CMD_PKT &&
                                      lq->lun_outcnt >= ha->execution_throttle) {
                                          continue;
                                  }
  
                                  if (sp->wdg_q_time != 0) {
--- 10268,10373 ----
   *      Function used to update timeout values and if timeout
   *      has occurred command will be aborted.
   *
   * Input:
   *      ha:     adapter state pointer.
   *
   * Context:
!  *      Kernel context.
   */
  static void
! ql_watchdog(ql_adapter_state_t *ha)
  {
          ql_link_t               *link;
          ql_tgt_t                *tq;
          uint16_t                index;
!         ql_adapter_state_t      *vha;
  
!         QL_PRINT_6(ha, "started\n");
  
+         for (vha = ha; vha != NULL; vha = vha->vp_next) {
                  /* Loop through all targets. */
                  for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
!                         for (link = vha->dev[index].first; link != NULL;
!                             link = link->next) {
                                  tq = link->base_address;
  
                                  /* Try to acquire device queue lock. */
                                  if (TRY_DEVICE_QUEUE_LOCK(tq) == 0) {
!                                         break;
                                  }
  
!                                 if (!(CFG_IST(ha,
!                                     CFG_ENABLE_LINK_DOWN_REPORTING)) &&
                                      (tq->port_down_retry_count == 0)) {
                                          /* Release device queue lock. */
                                          DEVICE_QUEUE_UNLOCK(tq);
                                          continue;
                                  }
+                                 ql_wdg_tq_list(vha, tq);
+                         }
+                 }
+         }
+         ha->watchdog_timer = WATCHDOG_TIME;
  
!         QL_PRINT_6(ha, "done\n");
! }
! 
! /*
!  * ql_wdg_tq_list
!  *      Timeout handler that runs in interrupt context. The
!  *      ql_adapter_state_t * argument is the parameter set up when the
!  *      timeout was initialized (state structure pointer).
!  *      Function used to update timeout values and if timeout
!  *      has occurred command will be aborted.
!  *
!  * Input:
!  *      ha:     adapter state pointer.
!  *      tq:     target queue pointer.
!  *      DEVICE_QUEUE_LOCK must be already obtained.
!  *
!  * Output:
!  *      Releases DEVICE_QUEUE_LOCK upon exit.
!  *
!  * Context:
!  *      Kernel context.
!  */
! static void
! ql_wdg_tq_list(ql_adapter_state_t *ha, ql_tgt_t *tq)
! {
!         ql_srb_t        *sp;
!         ql_link_t       *link, *next_cmd;
!         ql_lun_t        *lq;
!         boolean_t       q_sane, timeout = B_FALSE;
! 
!         QL_PRINT_6(ha, "started\n");
! 
!         /* Find out if this device is in a sane state */
!         if (tq->flags & (TQF_RSCN_RCVD | TQF_NEED_AUTHENTICATION |
!             TQF_QUEUE_SUSPENDED)) {
!                 q_sane = B_FALSE;
          } else {
!                 q_sane = B_TRUE;
          }
          /* Loop through commands on watchdog queue. */
!         for (link = tq->wdg.first; link != NULL; link = next_cmd) {
                  next_cmd = link->next;
                  sp = link->base_address;
                  lq = sp->lun_queue;
  
                  /*
!                  * For SCSI commands, if everything
!                  * seems to * be going fine and this
!                  * packet is stuck
!                  * because of throttling at LUN or
!                  * target level then do not decrement
!                  * the sp->wdg_q_time
                   */
                  if (ha->task_daemon_flags & STATE_ONLINE &&
!                     !(sp->flags & SRB_ISP_STARTED) &&
!                     q_sane == B_TRUE &&
!                     sp->flags & SRB_FCP_CMD_PKT &&
                      lq->lun_outcnt >= ha->execution_throttle) {
                          continue;
                  }
  
                  if (sp->wdg_q_time != 0) {
*** 9926,9962 ****
                                          /* Timeout? */
                                          if (sp->wdg_q_time != 0) {
                                                  continue;
                                          }
  
!                                         ql_remove_link(&tq->wdg, &sp->wdg);
!                                         sp->flags &= ~SRB_WATCHDOG_ENABLED;
  
!                                         if (sp->flags & SRB_ISP_STARTED) {
!                                                 ql_cmd_timeout(ha, tq, sp,
!                                                     set_flags, reset_flags);
  
!                                                 DEVICE_QUEUE_UNLOCK(tq);
!                                                 tq = NULL;
!                                                 next_cmd = NULL;
!                                                 next_device = NULL;
!                                                 index = DEVICE_HEAD_LIST_SIZE;
!                                         } else {
!                                                 ql_cmd_timeout(ha, tq, sp,
!                                                     set_flags, reset_flags);
                                          }
                                  }
                          }
  
                          /* Release device queue lock. */
-                         if (tq != NULL) {
                                  DEVICE_QUEUE_UNLOCK(tq);
-                         }
-                 }
-         }
  
!         QL_PRINT_6(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_cmd_timeout
   *      Command timeout handler.
--- 10376,10413 ----
                          /* Timeout? */
                          if (sp->wdg_q_time != 0) {
                                  continue;
                          }
  
!                         sp->flags |= SRB_COMMAND_TIMEOUT;
!                         timeout = B_TRUE;
!                 }
!         }
  
!         /*
!          * Loop through commands on watchdog queue and
!          * abort timed out commands.
!          */
!         if (timeout == B_TRUE) {
!                 for (link = tq->wdg.first; link != NULL; link = next_cmd) {
!                         sp = link->base_address;
!                         next_cmd = link->next;
  
!                         if (sp->flags & SRB_COMMAND_TIMEOUT) {
!                                 ql_remove_link(&tq->wdg, &sp->wdg);
!                                 sp->flags &= ~(SRB_WATCHDOG_ENABLED |
!                                     SRB_COMMAND_TIMEOUT);
!                                 ql_cmd_timeout(ha, tq, sp);
!                                 next_cmd = tq->wdg.first;
                          }
                  }
          }
  
          /* Release device queue lock. */
          DEVICE_QUEUE_UNLOCK(tq);
  
!         QL_PRINT_6(ha, "done\n");
  }
  
  /*
   * ql_cmd_timeout
   *      Command timeout handler.
*** 9963,9990 ****
   *
   * Input:
   *      ha:             adapter state pointer.
   *      tq:             target queue pointer.
   *      sp:             SRB pointer.
-  *      set_flags:      task daemon flags to set.
-  *      reset_flags:    task daemon flags to reset.
   *
   * Context:
!  *      Interrupt context, no mailbox commands allowed.
   */
- /* ARGSUSED */
  static void
! ql_cmd_timeout(ql_adapter_state_t *ha, ql_tgt_t *tq, ql_srb_t *sp,
!     uint32_t *set_flags, uint32_t *reset_flags)
  {
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (!(sp->flags & SRB_ISP_STARTED)) {
  
-                 EL(ha, "command timed out in driver = %ph\n", (void *)sp);
- 
                  REQUEST_RING_LOCK(ha);
  
                  /* if it's on a queue */
                  if (sp->cmd.head) {
                          /*
                           * The pending_cmds que needs to be
--- 10414,10438 ----
   *
   * Input:
   *      ha:             adapter state pointer.
   *      tq:             target queue pointer.
   *      sp:             SRB pointer.
   *
   * Context:
!  *      Kernel context.
   */
  static void
! ql_cmd_timeout(ql_adapter_state_t *ha, ql_tgt_t *tq, ql_srb_t *sp)
  {
!         int     rval = 0;
  
!         QL_PRINT_3(ha, "started\n");
  
          REQUEST_RING_LOCK(ha);
+         if (!(sp->flags & SRB_ISP_STARTED)) {
+                 EL(ha, "command timed out in driver, sp=%ph spf=%xh\n",
+                     (void *)sp, sp->flags);
  
                  /* if it's on a queue */
                  if (sp->cmd.head) {
                          /*
                           * The pending_cmds que needs to be
*** 10003,10116 ****
  
                  /* Ensure no retry */
                  sp->flags &= ~SRB_RETRY;
  
                  /* Call done routine to handle completion. */
!                 ql_done(&sp->cmd);
  
-                 DEVICE_QUEUE_LOCK(tq);
-         } else if (CFG_IST(ha, CFG_CTRL_8021)) {
-                 int             rval;
-                 uint32_t        index;
- 
                  EL(ha, "command timed out in isp=%ph, osc=%ph, index=%xh, "
                      "spf=%xh\n", (void *)sp,
                      (void *)ha->outstanding_cmds[sp->handle & OSC_INDEX_MASK],
                      sp->handle & OSC_INDEX_MASK, sp->flags);
  
!                 DEVICE_QUEUE_UNLOCK(tq);
! 
!                 INTR_LOCK(ha);
!                 ha->pha->xioctl->ControllerErrorCount++;
!                 if (sp->handle) {
!                         ha->pha->timeout_cnt++;
!                         index = sp->handle & OSC_INDEX_MASK;
!                         if (ha->pha->outstanding_cmds[index] == sp) {
!                                 sp->request_ring_ptr->entry_type =
!                                     INVALID_ENTRY_TYPE;
!                                 sp->request_ring_ptr->entry_count = 0;
!                                 ha->pha->outstanding_cmds[index] = 0;
!                         }
!                         INTR_UNLOCK(ha);
! 
!                         rval = ql_abort_command(ha, sp);
!                         if (rval == QL_FUNCTION_TIMEOUT ||
!                             rval == QL_LOCK_TIMEOUT ||
!                             rval == QL_FUNCTION_PARAMETER_ERROR ||
!                             ha->pha->timeout_cnt > TIMEOUT_THRESHOLD) {
!                                 *set_flags |= ISP_ABORT_NEEDED;
                                  EL(ha, "abort status=%xh, tc=%xh, isp_abort_"
                                      "needed\n", rval, ha->pha->timeout_cnt);
                          }
- 
-                         sp->handle = 0;
-                         sp->flags &= ~SRB_IN_TOKEN_ARRAY;
                  } else {
!                         INTR_UNLOCK(ha);
!                 }
  
-                 /* Set timeout status */
-                 sp->pkt->pkt_reason = CS_TIMEOUT;
- 
-                 /* Ensure no retry */
-                 sp->flags &= ~SRB_RETRY;
- 
-                 /* Call done routine to handle completion. */
-                 ql_done(&sp->cmd);
- 
-                 DEVICE_QUEUE_LOCK(tq);
- 
-         } else {
                  EL(ha, "command timed out in isp=%ph, osc=%ph, index=%xh, "
                      "spf=%xh, isp_abort_needed\n", (void *)sp,
                      (void *)ha->outstanding_cmds[sp->handle & OSC_INDEX_MASK],
                      sp->handle & OSC_INDEX_MASK, sp->flags);
  
-                 /* Release device queue lock. */
-                 DEVICE_QUEUE_UNLOCK(tq);
- 
                  INTR_LOCK(ha);
                  ha->pha->xioctl->ControllerErrorCount++;
                  INTR_UNLOCK(ha);
  
                  /* Set ISP needs to be reset */
                  sp->flags |= SRB_COMMAND_TIMEOUT;
  
                  if (CFG_IST(ha, CFG_DUMP_DRIVER_COMMAND_TIMEOUT)) {
!                         (void) ql_binary_fw_dump(ha, TRUE);
                  }
  
!                 *set_flags |= ISP_ABORT_NEEDED;
! 
!                 DEVICE_QUEUE_LOCK(tq);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
-  * ql_rst_aen
-  *      Processes asynchronous reset.
-  *
-  * Input:
-  *      ha = adapter state pointer.
-  *
-  * Context:
-  *      Kernel context.
-  */
- static void
- ql_rst_aen(ql_adapter_state_t *ha)
- {
-         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
- 
-         /* Issue marker command. */
-         (void) ql_marker(ha, 0, 0, MK_SYNC_ALL);
- 
-         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
- }
- 
- /*
   * ql_cmd_wait
   *      Stall driver until all outstanding commands are returned.
   *
   * Input:
   *      ha = adapter state pointer.
--- 10451,10511 ----
  
                  /* Ensure no retry */
                  sp->flags &= ~SRB_RETRY;
  
                  /* Call done routine to handle completion. */
!                 ql_done(&sp->cmd, B_FALSE);
!         } else if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                 REQUEST_RING_UNLOCK(ha);
!                 DEVICE_QUEUE_UNLOCK(tq);
  
                  EL(ha, "command timed out in isp=%ph, osc=%ph, index=%xh, "
                      "spf=%xh\n", (void *)sp,
                      (void *)ha->outstanding_cmds[sp->handle & OSC_INDEX_MASK],
                      sp->handle & OSC_INDEX_MASK, sp->flags);
  
!                 if (ha->pha->timeout_cnt++ > TIMEOUT_THRESHOLD ||
!                     (rval = ql_abort_io(ha, sp)) != QL_SUCCESS) {
!                         sp->flags |= SRB_COMMAND_TIMEOUT;
!                         TASK_DAEMON_LOCK(ha);
!                         ha->task_daemon_flags |= ISP_ABORT_NEEDED;
!                         TASK_DAEMON_UNLOCK(ha);
                          EL(ha, "abort status=%xh, tc=%xh, isp_abort_"
                              "needed\n", rval, ha->pha->timeout_cnt);
                  }
          } else {
!                 REQUEST_RING_UNLOCK(ha);
!                 DEVICE_QUEUE_UNLOCK(tq);
  
                  EL(ha, "command timed out in isp=%ph, osc=%ph, index=%xh, "
                      "spf=%xh, isp_abort_needed\n", (void *)sp,
                      (void *)ha->outstanding_cmds[sp->handle & OSC_INDEX_MASK],
                      sp->handle & OSC_INDEX_MASK, sp->flags);
  
                  INTR_LOCK(ha);
                  ha->pha->xioctl->ControllerErrorCount++;
                  INTR_UNLOCK(ha);
  
                  /* Set ISP needs to be reset */
                  sp->flags |= SRB_COMMAND_TIMEOUT;
  
                  if (CFG_IST(ha, CFG_DUMP_DRIVER_COMMAND_TIMEOUT)) {
!                         ADAPTER_STATE_LOCK(ha);
!                         ha->flags |= FW_DUMP_NEEDED;
!                         ADAPTER_STATE_UNLOCK(ha);
                  }
  
!                 TASK_DAEMON_LOCK(ha);
!                 ha->task_daemon_flags |= ISP_ABORT_NEEDED;
!                 TASK_DAEMON_UNLOCK(ha);
          }
+         DEVICE_QUEUE_LOCK(tq);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_cmd_wait
   *      Stall driver until all outstanding commands are returned.
   *
   * Input:
   *      ha = adapter state pointer.
*** 10124,10134 ****
          uint16_t                index;
          ql_link_t               *link;
          ql_tgt_t                *tq;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Wait for all outstanding commands to be returned. */
          (void) ql_wait_outstanding(ha);
  
          /*
--- 10519,10529 ----
          uint16_t                index;
          ql_link_t               *link;
          ql_tgt_t                *tq;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Wait for all outstanding commands to be returned. */
          (void) ql_wait_outstanding(ha);
  
          /*
*** 10139,10156 ****
                          for (link = vha->dev[index].first; link != NULL;
                              link = link->next) {
                                  tq = link->base_address;
                                  if (tq &&
                                      (!(tq->prli_svc_param_word_3 &
!                                     PRLI_W3_RETRY))) {
                                          (void) ql_abort_device(vha, tq, 0);
                                  }
                          }
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_wait_outstanding
   *      Wait for all outstanding commands to complete.
--- 10534,10552 ----
                          for (link = vha->dev[index].first; link != NULL;
                              link = link->next) {
                                  tq = link->base_address;
                                  if (tq &&
                                      (!(tq->prli_svc_param_word_3 &
!                                     PRLI_W3_RETRY) ||
!                                     ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
                                          (void) ql_abort_device(vha, tq, 0);
                                  }
                          }
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_wait_outstanding
   *      Wait for all outstanding commands to complete.
*** 10168,10199 ****
  ql_wait_outstanding(ql_adapter_state_t *ha)
  {
          ql_srb_t        *sp;
          uint16_t        index, count;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          count = ql_osc_wait_count;
!         for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
                  if (ha->pha->pending_cmds.first != NULL) {
                          ql_start_iocb(ha, NULL);
                          index = 1;
                  }
                  if ((sp = ha->pha->outstanding_cmds[index]) != NULL &&
                      (sp->flags & SRB_COMMAND_TIMEOUT) == 0) {
                          if (count-- != 0) {
                                  ql_delay(ha, 10000);
                                  index = 0;
                          } else {
!                                 EL(ha, "failed, sp=%ph, oci=%d, hdl=%xh\n",
!                                     (void *)sp, index, sp->handle);
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (index);
  }
  
  /*
--- 10564,10597 ----
  ql_wait_outstanding(ql_adapter_state_t *ha)
  {
          ql_srb_t        *sp;
          uint16_t        index, count;
  
!         QL_PRINT_3(ha, "started\n");
  
          count = ql_osc_wait_count;
!         for (index = 1; index < ha->pha->osc_max_cnt; index++) {
                  if (ha->pha->pending_cmds.first != NULL) {
                          ql_start_iocb(ha, NULL);
                          index = 1;
                  }
                  if ((sp = ha->pha->outstanding_cmds[index]) != NULL &&
+                     sp != QL_ABORTED_SRB(ha) &&
                      (sp->flags & SRB_COMMAND_TIMEOUT) == 0) {
                          if (count-- != 0) {
                                  ql_delay(ha, 10000);
                                  index = 0;
                          } else {
!                                 EL(ha, "still in OSC,sp=%ph,oci=%d,sph=%xh,"
!                                     "spf=%xh\n", (void *) sp, index, sp->handle,
!                                     sp->flags);
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (index);
  }
  
  /*
*** 10205,10224 ****
   *      DEVICE_QUEUE_LOCK must be released.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
! static void
  ql_restart_queues(ql_adapter_state_t *ha)
  {
          ql_link_t               *link, *link2;
          ql_tgt_t                *tq;
          ql_lun_t                *lq;
          uint16_t                index;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
                  for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                          for (link = vha->dev[index].first; link != NULL;
                              link = link->next) {
--- 10603,10622 ----
   *      DEVICE_QUEUE_LOCK must be released.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
! void
  ql_restart_queues(ql_adapter_state_t *ha)
  {
          ql_link_t               *link, *link2;
          ql_tgt_t                *tq;
          ql_lun_t                *lq;
          uint16_t                index;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(ha, "started\n");
  
          for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
                  for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                          for (link = vha->dev[index].first; link != NULL;
                              link = link->next) {
*** 10243,10253 ****
                                  DEVICE_QUEUE_UNLOCK(tq);
                          }
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_iidma
   *      Setup iiDMA parameters to firmware
--- 10641,10651 ----
                                  DEVICE_QUEUE_UNLOCK(tq);
                          }
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_iidma
   *      Setup iiDMA parameters to firmware
*** 10266,10306 ****
          ql_tgt_t        *tq;
          uint16_t        index;
          char            buf[256];
          uint32_t        data;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if ((CFG_IST(ha, CFG_CTRL_242581)) == 0) {
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
                  return;
          }
  
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                  for (link = ha->dev[index].first; link != NULL;
                      link = link->next) {
                          tq = link->base_address;
  
-                         /* Acquire device queue lock. */
-                         DEVICE_QUEUE_LOCK(tq);
- 
                          if ((tq->flags & TQF_IIDMA_NEEDED) == 0) {
-                                 DEVICE_QUEUE_UNLOCK(tq);
                                  continue;
                          }
  
                          tq->flags &= ~TQF_IIDMA_NEEDED;
  
                          if ((tq->loop_id > LAST_N_PORT_HDL) ||
                              (tq->iidma_rate == IIDMA_RATE_NDEF)) {
-                                 DEVICE_QUEUE_UNLOCK(tq);
                                  continue;
                          }
  
                          /* Get the iiDMA persistent data */
!                         if (tq->iidma_rate == IIDMA_RATE_INIT) {
!                                 (void) sprintf(buf,
                                      "iidma-rate-%02x%02x%02x%02x%02x"
                                      "%02x%02x%02x", tq->port_name[0],
                                      tq->port_name[1], tq->port_name[2],
                                      tq->port_name[3], tq->port_name[4],
                                      tq->port_name[5], tq->port_name[6],
--- 10664,10706 ----
          ql_tgt_t        *tq;
          uint16_t        index;
          char            buf[256];
          uint32_t        data;
  
!         QL_PRINT_3(ha, "started\n");
  
!         if (!CFG_IST(ha, CFG_IIDMA_SUPPORT)) {
!                 QL_PRINT_3(ha, "done\n");
                  return;
          }
  
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                  for (link = ha->dev[index].first; link != NULL;
                      link = link->next) {
                          tq = link->base_address;
  
                          if ((tq->flags & TQF_IIDMA_NEEDED) == 0) {
                                  continue;
                          }
  
+                         /* Acquire device queue lock. */
+                         DEVICE_QUEUE_LOCK(tq);
+ 
                          tq->flags &= ~TQF_IIDMA_NEEDED;
  
+                         /* Release device queue lock. */
+                         DEVICE_QUEUE_UNLOCK(tq);
+ 
                          if ((tq->loop_id > LAST_N_PORT_HDL) ||
+                             (tq->d_id.b24 == FS_MANAGEMENT_SERVER) ||
+                             (tq->flags & TQF_INITIATOR_DEVICE) ||
                              (tq->iidma_rate == IIDMA_RATE_NDEF)) {
                                  continue;
                          }
  
                          /* Get the iiDMA persistent data */
!                         (void) snprintf(buf, sizeof (buf),
                              "iidma-rate-%02x%02x%02x%02x%02x"
                              "%02x%02x%02x", tq->port_name[0],
                              tq->port_name[1], tq->port_name[2],
                              tq->port_name[3], tq->port_name[4],
                              tq->port_name[5], tq->port_name[6],
*** 10309,10360 ****
                                  if ((data = ql_get_prop(ha, buf)) ==
                                      0xffffffff) {
                                          tq->iidma_rate = IIDMA_RATE_NDEF;
                                  } else {
                                          switch (data) {
-                                         case IIDMA_RATE_1GB:
-                                         case IIDMA_RATE_2GB:
                                          case IIDMA_RATE_4GB:
                                          case IIDMA_RATE_10GB:
                                                  tq->iidma_rate = data;
                                                  break;
-                                         case IIDMA_RATE_8GB:
-                                                 if (CFG_IST(ha,
-                                                     CFG_CTRL_25XX)) {
-                                                         tq->iidma_rate = data;
-                                                 } else {
-                                                         tq->iidma_rate =
-                                                             IIDMA_RATE_4GB;
-                                                 }
-                                                 break;
                                          default:
                                                  EL(ha, "invalid data for "
                                                      "parameter: %s: %xh\n",
                                                      buf, data);
                                                  tq->iidma_rate =
                                                      IIDMA_RATE_NDEF;
                                                  break;
                                          }
                                  }
-                         }
  
                          /* Set the firmware's iiDMA rate */
!                         if (tq->iidma_rate <= IIDMA_RATE_MAX &&
!                             !(CFG_IST(ha, CFG_CTRL_8081))) {
                                  data = ql_iidma_rate(ha, tq->loop_id,
!                                     &tq->iidma_rate, EXT_IIDMA_MODE_SET);
                                  if (data != QL_SUCCESS) {
!                                         EL(ha, "mbx failed: %xh\n", data);
                                  }
                          }
- 
-                         /* Release device queue lock. */
-                         DEVICE_QUEUE_UNLOCK(tq);
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_abort_queues
   *      Abort all commands on device queues.
--- 10709,10754 ----
                          if ((data = ql_get_prop(ha, buf)) ==
                              0xffffffff) {
                                  tq->iidma_rate = IIDMA_RATE_NDEF;
                          } else {
                                  switch (data) {
                                  case IIDMA_RATE_4GB:
+                                 case IIDMA_RATE_8GB:
                                  case IIDMA_RATE_10GB:
+                                 case IIDMA_RATE_16GB:
+                                 case IIDMA_RATE_32GB:
                                          tq->iidma_rate = data;
                                          break;
                                  default:
                                          EL(ha, "invalid data for "
                                              "parameter: %s: %xh\n",
                                              buf, data);
                                          tq->iidma_rate =
                                              IIDMA_RATE_NDEF;
                                          break;
                                  }
                          }
  
+                         EL(ha, "d_id = %xh iidma_rate = %xh\n",
+                             tq->d_id.b24, tq->iidma_rate);
+ 
                          /* Set the firmware's iiDMA rate */
!                         if (!CFG_IST(ha, CFG_FCOE_SUPPORT)) {
!                                 if (tq->iidma_rate <= IIDMA_RATE_MAX) {
                                          data = ql_iidma_rate(ha, tq->loop_id,
!                                             &tq->iidma_rate,
!                                             EXT_IIDMA_MODE_SET);
                                          if (data != QL_SUCCESS) {
!                                                 EL(ha, "mbx failed: %xh\n",
!                                                     data);
                                          }
                                  }
                          }
                  }
+         }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_abort_queues
   *      Abort all commands on device queues.
*** 10363,10388 ****
   *      ha = adapter state pointer.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
! static void
  ql_abort_queues(ql_adapter_state_t *ha)
  {
          ql_link_t               *link;
          ql_tgt_t                *tq;
          ql_srb_t                *sp;
          uint16_t                index;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_10(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Return all commands in outstanding command list. */
          INTR_LOCK(ha);
  
          /* Place all commands in outstanding cmd list on device queue. */
!         for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) {
                  if (ha->pending_cmds.first != NULL) {
                          INTR_UNLOCK(ha);
                          ql_start_iocb(ha, NULL);
                          /* Delay for system */
                          ql_delay(ha, 10000);
--- 10757,10782 ----
   *      ha = adapter state pointer.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
! void
  ql_abort_queues(ql_adapter_state_t *ha)
  {
          ql_link_t               *link;
          ql_tgt_t                *tq;
          ql_srb_t                *sp;
          uint16_t                index;
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_10(ha, "started\n");
  
          /* Return all commands in outstanding command list. */
          INTR_LOCK(ha);
  
          /* Place all commands in outstanding cmd list on device queue. */
!         for (index = 1; index < ha->osc_max_cnt; index++) {
                  if (ha->pending_cmds.first != NULL) {
                          INTR_UNLOCK(ha);
                          ql_start_iocb(ha, NULL);
                          /* Delay for system */
                          ql_delay(ha, 10000);
*** 10389,10402 ****
                          INTR_LOCK(ha);
                          index = 1;
                  }
                  sp = ha->outstanding_cmds[index];
  
                  /* skip devices capable of FCP2 retrys */
!                 if ((sp != NULL) &&
!                     ((tq = sp->lun_queue->target_queue) != NULL) &&
!                     (!(tq->prli_svc_param_word_3 & PRLI_W3_RETRY))) {
                          ha->outstanding_cmds[index] = NULL;
                          sp->handle = 0;
                          sp->flags &= ~SRB_IN_TOKEN_ARRAY;
  
                          INTR_UNLOCK(ha);
--- 10783,10802 ----
                          INTR_LOCK(ha);
                          index = 1;
                  }
                  sp = ha->outstanding_cmds[index];
  
+                 if (sp && (sp == QL_ABORTED_SRB(ha) || sp->ha != ha)) {
+                         continue;
+                 }
+ 
                  /* skip devices capable of FCP2 retrys */
!                 if (sp != NULL &&
!                     (sp->lun_queue == NULL ||
!                     (tq = sp->lun_queue->target_queue) == NULL ||
!                     !(tq->prli_svc_param_word_3 & PRLI_W3_RETRY) ||
!                     ha->task_daemon_flags & ABORT_ISP_ACTIVE)) {
                          ha->outstanding_cmds[index] = NULL;
                          sp->handle = 0;
                          sp->flags &= ~SRB_IN_TOKEN_ARRAY;
  
                          INTR_UNLOCK(ha);
*** 10405,10431 ****
                          sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE;
                          sp->flags |= SRB_ISP_COMPLETED;
  
                          /* Call done routine to handle completions. */
                          sp->cmd.next = NULL;
!                         ql_done(&sp->cmd);
  
                          INTR_LOCK(ha);
                  }
          }
          INTR_UNLOCK(ha);
  
          for (vha = ha; vha != NULL; vha = vha->vp_next) {
!                 QL_PRINT_10(CE_CONT, "(%d,%d): abort instance\n",
!                     vha->instance, vha->vp_index);
                  for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                          for (link = vha->dev[index].first; link != NULL;
                              link = link->next) {
                                  tq = link->base_address;
                                  /* skip devices capable of FCP2 retrys */
                                  if (!(tq->prli_svc_param_word_3 &
!                                     PRLI_W3_RETRY)) {
                                          /*
                                           * Set port unavailable status and
                                           * return all commands on a devices
                                           * queues.
                                           */
--- 10805,10831 ----
                          sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE;
                          sp->flags |= SRB_ISP_COMPLETED;
  
                          /* Call done routine to handle completions. */
                          sp->cmd.next = NULL;
!                         ql_done(&sp->cmd, B_FALSE);
  
                          INTR_LOCK(ha);
                  }
          }
          INTR_UNLOCK(ha);
  
          for (vha = ha; vha != NULL; vha = vha->vp_next) {
!                 QL_PRINT_10(vha, "abort instance\n");
                  for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                          for (link = vha->dev[index].first; link != NULL;
                              link = link->next) {
                                  tq = link->base_address;
                                  /* skip devices capable of FCP2 retrys */
                                  if (!(tq->prli_svc_param_word_3 &
!                                     PRLI_W3_RETRY) ||
!                                     ha->task_daemon_flags & ABORT_ISP_ACTIVE) {
                                          /*
                                           * Set port unavailable status and
                                           * return all commands on a devices
                                           * queues.
                                           */
*** 10432,10442 ****
                                          ql_abort_device_queues(ha, tq);
                                  }
                          }
                  }
          }
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_abort_device_queues
   *      Abort all commands on device queues.
--- 10832,10842 ----
                                          ql_abort_device_queues(ha, tq);
                                  }
                          }
                  }
          }
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_abort_device_queues
   *      Abort all commands on device queues.
*** 10452,10478 ****
  {
          ql_link_t       *lun_link, *cmd_link;
          ql_srb_t        *sp;
          ql_lun_t        *lq;
  
!         QL_PRINT_10(CE_CONT, "(%d): started\n", ha->instance);
  
          DEVICE_QUEUE_LOCK(tq);
  
          for (lun_link = tq->lun_queues.first; lun_link != NULL;
              lun_link = lun_link->next) {
                  lq = lun_link->base_address;
  
                  cmd_link = lq->cmd.first;
                  while (cmd_link != NULL) {
                          sp = cmd_link->base_address;
  
-                         if (sp->flags & SRB_ABORT) {
-                                 cmd_link = cmd_link->next;
-                                 continue;
-                         }
- 
                          /* Remove srb from device cmd queue. */
                          ql_remove_link(&lq->cmd, &sp->cmd);
  
                          sp->flags &= ~SRB_IN_DEVICE_QUEUE;
  
--- 10852,10874 ----
  {
          ql_link_t       *lun_link, *cmd_link;
          ql_srb_t        *sp;
          ql_lun_t        *lq;
  
!         QL_PRINT_10(ha, "started\n");
  
          DEVICE_QUEUE_LOCK(tq);
+         ql_requeue_pending_cmds(ha, tq);
  
          for (lun_link = tq->lun_queues.first; lun_link != NULL;
              lun_link = lun_link->next) {
                  lq = lun_link->base_address;
  
                  cmd_link = lq->cmd.first;
                  while (cmd_link != NULL) {
                          sp = cmd_link->base_address;
  
                          /* Remove srb from device cmd queue. */
                          ql_remove_link(&lq->cmd, &sp->cmd);
  
                          sp->flags &= ~SRB_IN_DEVICE_QUEUE;
  
*** 10480,10490 ****
  
                          /* Set ending status. */
                          sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE;
  
                          /* Call done routine to handle completion. */
!                         ql_done(&sp->cmd);
  
                          /* Delay for system */
                          ql_delay(ha, 10000);
  
                          DEVICE_QUEUE_LOCK(tq);
--- 10876,10886 ----
  
                          /* Set ending status. */
                          sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE;
  
                          /* Call done routine to handle completion. */
!                         ql_done(&sp->cmd, B_FALSE);
  
                          /* Delay for system */
                          ql_delay(ha, 10000);
  
                          DEVICE_QUEUE_LOCK(tq);
*** 10491,10501 ****
                          cmd_link = lq->cmd.first;
                  }
          }
          DEVICE_QUEUE_UNLOCK(tq);
  
!         QL_PRINT_10(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_loop_resync
   *      Resync with fibre channel devices.
--- 10887,10897 ----
                          cmd_link = lq->cmd.first;
                  }
          }
          DEVICE_QUEUE_UNLOCK(tq);
  
!         QL_PRINT_10(ha, "done\n");
  }
  
  /*
   * ql_loop_resync
   *      Resync with fibre channel devices.
*** 10502,10523 ****
   *
   * Input:
   *      ha = adapter state pointer.
   *      DEVICE_QUEUE_LOCK must be released.
   *
-  * Returns:
-  *      ql local function return status code.
-  *
   * Context:
   *      Kernel context.
   */
! static int
  ql_loop_resync(ql_adapter_state_t *ha)
  {
          int rval;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (ha->flags & IP_INITIALIZED) {
                  (void) ql_shutdown_ip(ha);
          }
  
--- 10898,10916 ----
   *
   * Input:
   *      ha = adapter state pointer.
   *      DEVICE_QUEUE_LOCK must be released.
   *
   * Context:
   *      Kernel context.
   */
! static void
  ql_loop_resync(ql_adapter_state_t *ha)
  {
          int rval;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (ha->flags & IP_INITIALIZED) {
                  (void) ql_shutdown_ip(ha);
          }
  
*** 10528,10543 ****
          TASK_DAEMON_UNLOCK(ha);
  
          /* Set loop online, if it really is. */
          if (rval == QL_SUCCESS) {
                  ql_loop_online(ha);
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          } else {
                  EL(ha, "failed, rval = %xh\n", rval);
          }
- 
-         return (rval);
  }
  
  /*
   * ql_loop_online
   *      Set loop online status if it really is online.
--- 10921,10934 ----
          TASK_DAEMON_UNLOCK(ha);
  
          /* Set loop online, if it really is. */
          if (rval == QL_SUCCESS) {
                  ql_loop_online(ha);
!                 QL_PRINT_3(ha, "done\n");
          } else {
                  EL(ha, "failed, rval = %xh\n", rval);
          }
  }
  
  /*
   * ql_loop_online
   *      Set loop online status if it really is online.
*** 10552,10562 ****
  void
  ql_loop_online(ql_adapter_state_t *ha)
  {
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Inform the FC Transport that the hardware is online. */
          for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
                  if (!(vha->task_daemon_flags &
                      (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
--- 10943,10953 ----
  void
  ql_loop_online(ql_adapter_state_t *ha)
  {
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Inform the FC Transport that the hardware is online. */
          for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
                  if (!(vha->task_daemon_flags &
                      (LOOP_RESYNC_NEEDED | LOOP_DOWN))) {
*** 10586,10596 ****
          ql_awaken_task_daemon(ha, NULL, 0, 0);
  
          /* Restart device queues that may have been stopped. */
          ql_restart_queues(ha);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_fca_handle_to_state
   *      Verifies handle to be correct.
--- 10977,10987 ----
          ql_awaken_task_daemon(ha, NULL, 0, 0);
  
          /* Restart device queues that may have been stopped. */
          ql_restart_queues(ha);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_fca_handle_to_state
   *      Verifies handle to be correct.
*** 10627,10637 ****
                  }
          }
  
          if (ha == NULL) {
                  /*EMPTY*/
!                 QL_PRINT_2(CE_CONT, "failed\n");
          }
  
  #endif /* QL_DEBUG_ROUTINES */
  
          return ((ql_adapter_state_t *)fca_handle);
--- 11018,11028 ----
                  }
          }
  
          if (ha == NULL) {
                  /*EMPTY*/
!                 QL_PRINT_2(ha, "failed\n");
          }
  
  #endif /* QL_DEBUG_ROUTINES */
  
          return ((ql_adapter_state_t *)fca_handle);
*** 10724,10747 ****
  static int
  ql_kstat_update(kstat_t *ksp, int rw)
  {
          int                     rval;
  
!         QL_PRINT_3(CE_CONT, "started\n");
  
          if (rw == KSTAT_WRITE) {
                  rval = EACCES;
          } else {
                  rval = 0;
          }
  
          if (rval != 0) {
                  /*EMPTY*/
!                 QL_PRINT_2(CE_CONT, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "done\n");
          }
          return (rval);
  }
  
  /*
--- 11115,11138 ----
  static int
  ql_kstat_update(kstat_t *ksp, int rw)
  {
          int     rval;
  
!         QL_PRINT_3(ksp->ks_private, "started\n");
  
          if (rw == KSTAT_WRITE) {
                  rval = EACCES;
          } else {
                  rval = 0;
          }
  
          if (rval != 0) {
                  /*EMPTY*/
!                 QL_PRINT_2(ksp->ks_private, "failed, rval = %xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ksp->ks_private, "done\n");
          }
          return (rval);
  }
  
  /*
*** 10766,10780 ****
          int             rval;
          uint32_t        size_to_offset;
          uint32_t        size_to_compare;
          int             erase_all;
  
!         if (CFG_IST(ha, CFG_CTRL_24258081)) {
                  return (ql_24xx_load_flash(ha, dp, size, 0));
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          size_to_compare = 0x20000;
          size_to_offset = 0;
          erase_all = 0;
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
--- 11157,11171 ----
          int             rval;
          uint32_t        size_to_offset;
          uint32_t        size_to_compare;
          int             erase_all;
  
!         if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                  return (ql_24xx_load_flash(ha, dp, size, 0));
          }
  
!         QL_PRINT_3(ha, "started\n");
  
          size_to_compare = 0x20000;
          size_to_offset = 0;
          erase_all = 0;
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
*** 10793,10804 ****
                  rval = QL_FUNCTION_PARAMETER_ERROR;
                  EL(ha, "failed=%xh\n", rval);
                  return (rval);
          }
  
-         GLOBAL_HW_LOCK();
- 
          /* Enable Flash Read/Write. */
          ql_flash_enable(ha);
  
          /* Erase flash prior to write. */
          rval = ql_erase_flash(ha, erase_all);
--- 11184,11193 ----
*** 10818,10834 ****
                  }
          }
  
          ql_flash_disable(ha);
  
-         GLOBAL_HW_UNLOCK();
- 
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 11207,11221 ----
                  }
          }
  
          ql_flash_disable(ha);
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 10849,10859 ****
  static int
  ql_program_flash_address(ql_adapter_state_t *ha, uint32_t addr, uint8_t data)
  {
          int rval;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
                  ql_write_flash_byte(ha, 0x5555, 0xa0);
                  ql_write_flash_byte(ha, addr, data);
          } else {
--- 11236,11246 ----
  static int
  ql_program_flash_address(ql_adapter_state_t *ha, uint32_t addr, uint8_t data)
  {
          int rval;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
                  ql_write_flash_byte(ha, 0x5555, 0xa0);
                  ql_write_flash_byte(ha, addr, data);
          } else {
*** 10869,10879 ****
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 11256,11266 ----
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 10898,10911 ****
          uint32_t        ssize;
          uint32_t        cnt;
          uint8_t         *bfp;
          uint8_t         *tmp;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if ((CFG_IST(ha, CFG_SBUS_CARD)) && !erase_all) {
- 
                  if (ql_flash_sbus_fpga == 1) {
                          ssize = QL_SBUS_FCODE_SIZE;
                          sStartAddr = QL_FCODE_OFFSET;
                  } else {
                          ssize = QL_FPGA_SIZE;
--- 11285,11297 ----
          uint32_t        ssize;
          uint32_t        cnt;
          uint8_t         *bfp;
          uint8_t         *tmp;
  
!         QL_PRINT_3(ha, "started\n");
  
          if ((CFG_IST(ha, CFG_SBUS_CARD)) && !erase_all) {
                  if (ql_flash_sbus_fpga == 1) {
                          ssize = QL_SBUS_FCODE_SIZE;
                          sStartAddr = QL_FCODE_OFFSET;
                  } else {
                          ssize = QL_FPGA_SIZE;
*** 10916,10933 ****
  
                  bfp = (uint8_t *)kmem_zalloc(ssize, KM_SLEEP);
  
                  /* Save the section of flash we're not updating to buffer */
                  tmp = bfp;
!                 for (cnt = sStartAddr; cnt < ssize+sStartAddr; cnt++) {
                          /* Allow other system activity. */
                          if (cnt % 0x1000 == 0) {
                                  ql_delay(ha, 10000);
                          }
                          *tmp++ = (uint8_t)ql_read_flash_byte(ha, cnt);
                  }
-         }
  
          /* Chip Erase Command Sequence */
          ql_write_flash_byte(ha, 0x5555, 0xaa);
          ql_write_flash_byte(ha, 0x2aaa, 0x55);
          ql_write_flash_byte(ha, 0x5555, 0x80);
--- 11302,11318 ----
  
                  bfp = (uint8_t *)kmem_zalloc(ssize, KM_SLEEP);
  
                  /* Save the section of flash we're not updating to buffer */
                  tmp = bfp;
!                 for (cnt = sStartAddr; cnt < ssize + sStartAddr; cnt++) {
                          /* Allow other system activity. */
                          if (cnt % 0x1000 == 0) {
                                  ql_delay(ha, 10000);
                          }
                          *tmp++ = (uint8_t)ql_read_flash_byte(ha, cnt);
                  }
  
                  /* Chip Erase Command Sequence */
                  ql_write_flash_byte(ha, 0x5555, 0xaa);
                  ql_write_flash_byte(ha, 0x2aaa, 0x55);
                  ql_write_flash_byte(ha, 0x5555, 0x80);
*** 10938,10978 ****
          ql_delay(ha, erase_delay);
  
          /* Wait for erase to complete. */
          rval = ql_poll_flash(ha, 0, 0x80);
  
!         if (rval != QL_SUCCESS) {
!                 EL(ha, "failed=%xh\n", rval);
!                 if (CFG_IST(ha, CFG_SBUS_CARD)) {
!                         kmem_free(bfp, ssize);
!                 }
!                 return (rval);
!         }
! 
!         /* restore the section we saved in the buffer */
!         if ((CFG_IST(ha, CFG_SBUS_CARD)) && !erase_all) {
                  /* Restore the section we saved off */
                  tmp = bfp;
!                 for (cnt = sStartAddr; cnt < ssize+sStartAddr; cnt++) {
                          /* Allow other system activity. */
                          if (cnt % 0x1000 == 0) {
                                  ql_delay(ha, 10000);
                          }
!                         rval = ql_program_flash_address(ha, cnt, *tmp++);
                          if (rval != QL_SUCCESS) {
                                  break;
                          }
                  }
! 
                  kmem_free(bfp, ssize);
          }
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 11323,11369 ----
                  ql_delay(ha, erase_delay);
  
                  /* Wait for erase to complete. */
                  rval = ql_poll_flash(ha, 0, 0x80);
  
!                 if (rval == QL_SUCCESS) {
                          /* Restore the section we saved off */
                          tmp = bfp;
!                         for (cnt = sStartAddr; cnt < ssize + sStartAddr;
!                             cnt++) {
                                  /* Allow other system activity. */
                                  if (cnt % 0x1000 == 0) {
                                          ql_delay(ha, 10000);
                                  }
!                                 rval = ql_program_flash_address(ha, cnt,
!                                     *tmp++);
                                  if (rval != QL_SUCCESS) {
                                          break;
                                  }
                          }
!                 }
                  kmem_free(bfp, ssize);
+         } else {
+                 /* Chip Erase Command Sequence */
+                 ql_write_flash_byte(ha, 0x5555, 0xaa);
+                 ql_write_flash_byte(ha, 0x2aaa, 0x55);
+                 ql_write_flash_byte(ha, 0x5555, 0x80);
+                 ql_write_flash_byte(ha, 0x5555, 0xaa);
+                 ql_write_flash_byte(ha, 0x2aaa, 0x55);
+                 ql_write_flash_byte(ha, 0x5555, 0x10);
+ 
+                 ql_delay(ha, erase_delay);
+ 
+                 /* Wait for erase to complete. */
+                 rval = ql_poll_flash(ha, 0, 0x80);
          }
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 10995,11005 ****
  {
          uint8_t         flash_data;
          uint32_t        cnt;
          int             rval = QL_FUNCTION_FAILED;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          poll_data = (uint8_t)(poll_data & BIT_7);
  
          /* Wait for 30 seconds for command to finish. */
          for (cnt = 30000000; cnt; cnt--) {
--- 11386,11396 ----
  {
          uint8_t         flash_data;
          uint32_t        cnt;
          int             rval = QL_FUNCTION_FAILED;
  
!         QL_PRINT_3(ha, "started\n");
  
          poll_data = (uint8_t)(poll_data & BIT_7);
  
          /* Wait for 30 seconds for command to finish. */
          for (cnt = 30000000; cnt; cnt--) {
*** 11017,11027 ****
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 11408,11418 ----
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 11037,11047 ****
  void
  ql_flash_enable(ql_adapter_state_t *ha)
  {
          uint16_t        data;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Enable Flash Read/Write. */
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
                  data = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle,
                      (uint16_t *)(ha->sbus_fpga_iobase + FPGA_CONF));
--- 11428,11438 ----
  void
  ql_flash_enable(ql_adapter_state_t *ha)
  {
          uint16_t        data;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Enable Flash Read/Write. */
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
                  data = (uint16_t)ddi_get16(ha->sbus_fpga_dev_handle,
                      (uint16_t *)(ha->sbus_fpga_iobase + FPGA_CONF));
*** 11063,11073 ****
                  ql_write_flash_byte(ha, 0x2aaa, 0x55);
                  ql_write_flash_byte(ha, 0x5555, 0xf0);
          }
          (void) ql_read_flash_byte(ha, 0);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_flash_disable
   *      Disable flash and allow RISC to run.
--- 11454,11464 ----
                  ql_write_flash_byte(ha, 0x2aaa, 0x55);
                  ql_write_flash_byte(ha, 0x5555, 0xf0);
          }
          (void) ql_read_flash_byte(ha, 0);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_flash_disable
   *      Disable flash and allow RISC to run.
*** 11081,11091 ****
  void
  ql_flash_disable(ql_adapter_state_t *ha)
  {
          uint16_t        data;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
                  /*
                   * Lock the flash back up.
                   */
--- 11472,11482 ----
  void
  ql_flash_disable(ql_adapter_state_t *ha)
  {
          uint16_t        data;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (CFG_IST(ha, CFG_SBUS_CARD)) {
                  /*
                   * Lock the flash back up.
                   */
*** 11101,11111 ****
                  data = (uint16_t)(RD16_IO_REG(ha, ctrl_status) &
                      ~ISP_FLASH_ENABLE);
                  WRT16_IO_REG(ha, ctrl_status, data);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_write_flash_byte
   *      Write byte to flash.
--- 11492,11502 ----
                  data = (uint16_t)(RD16_IO_REG(ha, ctrl_status) &
                      ~ISP_FLASH_ENABLE);
                  WRT16_IO_REG(ha, ctrl_status, data);
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_write_flash_byte
   *      Write byte to flash.
*** 11135,11145 ****
                  uint16_t bank_select;
  
                  /* Setup bit 16 of flash address. */
                  bank_select = (uint16_t)RD16_IO_REG(ha, ctrl_status);
  
!                 if (CFG_IST(ha, CFG_CTRL_6322)) {
                          bank_select = (uint16_t)(bank_select & ~0xf0);
                          bank_select = (uint16_t)(bank_select |
                              ((addr >> 12 & 0xf0) | ISP_FLASH_64K_BANK));
                          WRT16_IO_REG(ha, ctrl_status, bank_select);
                  } else {
--- 11526,11536 ----
                  uint16_t bank_select;
  
                  /* Setup bit 16 of flash address. */
                  bank_select = (uint16_t)RD16_IO_REG(ha, ctrl_status);
  
!                 if (ha->device_id == 0x2322 || ha->device_id == 0x6322) {
                          bank_select = (uint16_t)(bank_select & ~0xf0);
                          bank_select = (uint16_t)(bank_select |
                              ((addr >> 12 & 0xf0) | ISP_FLASH_64K_BANK));
                          WRT16_IO_REG(ha, ctrl_status, bank_select);
                  } else {
*** 11197,11207 ****
          } else {
                  uint16_t        bank_select;
  
                  /* Setup bit 16 of flash address. */
                  bank_select = RD16_IO_REG(ha, ctrl_status);
!                 if (CFG_IST(ha, CFG_CTRL_6322)) {
                          bank_select = (uint16_t)(bank_select & ~0xf0);
                          bank_select = (uint16_t)(bank_select |
                              ((addr >> 12 & 0xf0) | ISP_FLASH_64K_BANK));
                          WRT16_IO_REG(ha, ctrl_status, bank_select);
                  } else {
--- 11588,11598 ----
          } else {
                  uint16_t        bank_select;
  
                  /* Setup bit 16 of flash address. */
                  bank_select = RD16_IO_REG(ha, ctrl_status);
!                 if (ha->device_id == 0x2322 || ha->device_id == 0x6322) {
                          bank_select = (uint16_t)(bank_select & ~0xf0);
                          bank_select = (uint16_t)(bank_select |
                              ((addr >> 12 & 0xf0) | ISP_FLASH_64K_BANK));
                          WRT16_IO_REG(ha, ctrl_status, bank_select);
                  } else {
*** 11249,11266 ****
          int                     rval;
          uint32_t                fdata = 0;
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          rval = ql_24xx_read_flash(ha, FLASH_CONF_ADDR | 0x3AB, &fdata);
! 
!         if (rval != QL_SUCCESS || fdata == 0 || CFG_IST(ha, CFG_CTRL_2581)) {
                  fdata = 0;
                  rval = ql_24xx_read_flash(ha, FLASH_CONF_ADDR |
!                     (CFG_IST(ha, CFG_CTRL_2422) ? 0x39F : 0x49F), &fdata);
          }
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "24xx read_flash failed=%xh\n", rval);
          } else if (fdata != 0) {
--- 11640,11662 ----
          int                     rval;
          uint32_t                fdata = 0;
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(ha, "started\n");
  
          rval = ql_24xx_read_flash(ha, FLASH_CONF_ADDR | 0x3AB, &fdata);
!         if (CFG_IST(ha, CFG_CTRL_24XX)) {
!                 if (rval != QL_SUCCESS || fdata == 0) {
                          fdata = 0;
+                         rval = ql_24xx_read_flash(ha, FLASH_CONF_ADDR | 0x39F,
+                             &fdata);
+                 }
+         } else {
+                 fdata = 0;
                  rval = ql_24xx_read_flash(ha, FLASH_CONF_ADDR |
!                     (CFG_IST(ha, CFG_CTRL_25XX) ? 0x49F : 0x39F), &fdata);
          }
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "24xx read_flash failed=%xh\n", rval);
          } else if (fdata != 0) {
*** 11271,11281 ****
                  xp->fdesc.flash_manuf = ATMEL_FLASH;
                  xp->fdesc.flash_id = ATMEL_FLASHID_1024K;
                  xp->fdesc.flash_len = 0;
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 11667,11677 ----
                  xp->fdesc.flash_manuf = ATMEL_FLASH;
                  xp->fdesc.flash_id = ATMEL_FLASHID_1024K;
                  xp->fdesc.flash_len = 0;
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 11302,11335 ****
          uint32_t                cnt, rest_addr, fdata, wc;
          dma_mem_t               dmabuf = {0};
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(CE_CONT, "(%d): started, faddr=%xh, size=%xh\n",
              ha->instance, faddr, size);
  
          /* start address must be 32 bit word aligned */
          if ((faddr & 0x3) != 0) {
                  EL(ha, "incorrect buffer size alignment\n");
                  return (QL_FUNCTION_PARAMETER_ERROR);
          }
  
          /* Allocate DMA buffer */
!         if (CFG_IST(ha, CFG_CTRL_2581)) {
                  if ((rval = ql_get_dma_mem(ha, &dmabuf, 0xffff,
                      LITTLE_ENDIAN_DMA, QL_DMA_DATA_ALIGN)) !=
                      QL_SUCCESS) {
                          EL(ha, "dma alloc failed, rval=%xh\n", rval);
                          return (rval);
                  }
          }
  
-         GLOBAL_HW_LOCK();
- 
          /* Enable flash write */
          if ((rval = ql_24xx_unprotect_flash(ha)) != QL_SUCCESS) {
-                 GLOBAL_HW_UNLOCK();
                  EL(ha, "unprotect_flash failed, rval=%xh\n", rval);
                  ql_free_phys(ha, &dmabuf);
                  return (rval);
          }
  
--- 11698,11728 ----
          uint32_t                cnt, rest_addr, fdata, wc;
          dma_mem_t               dmabuf = {0};
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(ha, "started, faddr=%xh, size=%xh\n",
              ha->instance, faddr, size);
  
          /* start address must be 32 bit word aligned */
          if ((faddr & 0x3) != 0) {
                  EL(ha, "incorrect buffer size alignment\n");
                  return (QL_FUNCTION_PARAMETER_ERROR);
          }
  
          /* Allocate DMA buffer */
!         if (CFG_IST(ha, CFG_FLASH_DMA_SUPPORT)) {
                  if ((rval = ql_get_dma_mem(ha, &dmabuf, 0xffff,
                      LITTLE_ENDIAN_DMA, QL_DMA_DATA_ALIGN)) !=
                      QL_SUCCESS) {
                          EL(ha, "dma alloc failed, rval=%xh\n", rval);
                          return (rval);
                  }
          }
  
          /* Enable flash write */
          if ((rval = ql_24xx_unprotect_flash(ha)) != QL_SUCCESS) {
                  EL(ha, "unprotect_flash failed, rval=%xh\n", rval);
                  ql_free_phys(ha, &dmabuf);
                  return (rval);
          }
  
*** 11345,11365 ****
          size = (size + 3) >> 2; /* Round up & convert to dwords */
  
          while (cnt < size) {
                  /* Beginning of a sector? */
                  if ((faddr & rest_addr) == 0) {
!                         if (CFG_IST(ha, CFG_CTRL_8021)) {
                                  fdata = ha->flash_data_addr | faddr;
                                  rval = ql_8021_rom_erase(ha, fdata);
                                  if (rval != QL_SUCCESS) {
                                          EL(ha, "8021 erase sector status="
                                              "%xh, start=%xh, end=%xh"
                                              "\n", rval, fdata,
                                              fdata + rest_addr);
                                          break;
                                  }
!                         } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
                                  fdata = ha->flash_data_addr | faddr;
                                  rval = ql_flash_access(ha,
                                      FAC_ERASE_SECTOR, fdata, fdata +
                                      rest_addr, 0);
                                  if (rval != QL_SUCCESS) {
--- 11738,11758 ----
          size = (size + 3) >> 2; /* Round up & convert to dwords */
  
          while (cnt < size) {
                  /* Beginning of a sector? */
                  if ((faddr & rest_addr) == 0) {
!                         if (CFG_IST(ha, CFG_CTRL_82XX)) {
                                  fdata = ha->flash_data_addr | faddr;
                                  rval = ql_8021_rom_erase(ha, fdata);
                                  if (rval != QL_SUCCESS) {
                                          EL(ha, "8021 erase sector status="
                                              "%xh, start=%xh, end=%xh"
                                              "\n", rval, fdata,
                                              fdata + rest_addr);
                                          break;
                                  }
!                         } else if (CFG_IST(ha, CFG_FLASH_ACC_SUPPORT)) {
                                  fdata = ha->flash_data_addr | faddr;
                                  rval = ql_flash_access(ha,
                                      FAC_ERASE_SECTOR, fdata, fdata +
                                      rest_addr, 0);
                                  if (rval != QL_SUCCESS) {
*** 11393,11403 ****
                                  }
                          }
                  }
  
                  /* Write data */
!                 if (CFG_IST(ha, CFG_CTRL_2581) &&
                      ((faddr & 0x3f) == 0)) {
                          /*
                           * Limit write up to sector boundary.
                           */
                          wc = ((~faddr & (rest_addr>>1)) + 1);
--- 11786,11796 ----
                                  }
                          }
                  }
  
                  /* Write data */
!                 if (CFG_IST(ha, CFG_FLASH_DMA_SUPPORT) &&
                      ((faddr & 0x3f) == 0)) {
                          /*
                           * Limit write up to sector boundary.
                           */
                          wc = ((~faddr & (rest_addr>>1)) + 1);
*** 11444,11462 ****
                  }
          }
  
          ql_24xx_protect_flash(ha);
  
          ql_free_phys(ha, &dmabuf);
  
-         GLOBAL_HW_UNLOCK();
- 
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
          return (rval);
  }
  
  /*
--- 11837,11855 ----
                  }
          }
  
          ql_24xx_protect_flash(ha);
  
+         if (CFG_IST(ha, CFG_FLASH_DMA_SUPPORT)) {
                  ql_free_phys(ha, &dmabuf);
+         }
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
          return (rval);
  }
  
  /*
*** 11479,11489 ****
  {
          uint32_t                timer;
          int                     rval = QL_SUCCESS;
          ql_adapter_state_t      *ha = vha->pha;
  
!         if (CFG_IST(ha, CFG_CTRL_8021)) {
                  if ((rval = ql_8021_rom_read(ha, faddr, bp)) != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return (rval);
          }
--- 11872,11882 ----
  {
          uint32_t                timer;
          int                     rval = QL_SUCCESS;
          ql_adapter_state_t      *ha = vha->pha;
  
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
                  if ((rval = ql_8021_rom_read(ha, faddr, bp)) != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return (rval);
          }
*** 11535,11545 ****
  {
          uint32_t                timer, fdata;
          int                     rval = QL_SUCCESS;
          ql_adapter_state_t      *ha = vha->pha;
  
!         if (CFG_IST(ha, CFG_CTRL_8021)) {
                  if ((rval = ql_8021_rom_write(ha, addr, data)) != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return (rval);
          }
--- 11928,11938 ----
  {
          uint32_t                timer, fdata;
          int                     rval = QL_SUCCESS;
          ql_adapter_state_t      *ha = vha->pha;
  
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
                  if ((rval = ql_8021_rom_write(ha, addr, data)) != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return (rval);
          }
*** 11555,11565 ****
          for (timer = 3000000; timer; timer--) {
                  if ((RD32_IO_REG(ha, flash_address) & FLASH_DATA_FLAG) == 0) {
                          /* Check flash write in progress. */
                          if ((addr & FLASH_ADDR_MASK) == FLASH_CONF_ADDR) {
                                  (void) ql_24xx_read_flash(ha,
!                                     FLASH_CONF_ADDR | 0x005, &fdata);
                                  if (!(fdata & BIT_0)) {
                                          break;
                                  }
                          } else {
                                  break;
--- 11948,11958 ----
          for (timer = 3000000; timer; timer--) {
                  if ((RD32_IO_REG(ha, flash_address) & FLASH_DATA_FLAG) == 0) {
                          /* Check flash write in progress. */
                          if ((addr & FLASH_ADDR_MASK) == FLASH_CONF_ADDR) {
                                  (void) ql_24xx_read_flash(ha,
!                                     FLASH_CONF_ADDR | 0x105, &fdata);
                                  if (!(fdata & BIT_0)) {
                                          break;
                                  }
                          } else {
                                  break;
*** 11592,11636 ****
   */
  int
  ql_24xx_unprotect_flash(ql_adapter_state_t *vha)
  {
          int                     rval;
!         uint32_t                fdata;
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (CFG_IST(ha, CFG_CTRL_8021)) {
                  (void) ql_8021_rom_wrsr(ha, xp->fdesc.write_enable_bits);
                  rval = ql_8021_rom_wrsr(ha, xp->fdesc.write_enable_bits);
                  if (rval != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return (rval);
          }
!         if (CFG_IST(ha, CFG_CTRL_81XX)) {
                  if (ha->task_daemon_flags & FIRMWARE_UP) {
!                         if ((rval = ql_flash_access(ha, FAC_WRT_ENABLE, 0, 0,
!                             0)) != QL_SUCCESS) {
!                                 EL(ha, "status=%xh\n", rval);
                          }
!                         QL_PRINT_3(CE_CONT, "(%d): 8100 done\n",
!                             ha->instance);
!                         return (rval);
                  }
          } else {
                  /* Enable flash write. */
                  WRT32_IO_REG(ha, ctrl_status,
                      RD32_IO_REG(ha, ctrl_status) | ISP_FLASH_ENABLE);
                  RD32_IO_REG(ha, ctrl_status);   /* PCI Posting. */
          }
  
          /*
!          * Remove block write protection (SST and ST) and
!          * Sector/Block Protection Register Lock (SST, ST, ATMEL).
!          * Unprotect sectors.
           */
          (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x100 |
              xp->fdesc.write_statusreg_cmd, xp->fdesc.write_enable_bits);
  
          if (xp->fdesc.unprotect_sector_cmd != 0) {
--- 11985,12051 ----
   */
  int
  ql_24xx_unprotect_flash(ql_adapter_state_t *vha)
  {
          int                     rval;
!         uint32_t                fdata, timer;
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(ha, "started\n");
  
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
                  (void) ql_8021_rom_wrsr(ha, xp->fdesc.write_enable_bits);
                  rval = ql_8021_rom_wrsr(ha, xp->fdesc.write_enable_bits);
                  if (rval != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return (rval);
          }
!         if (CFG_IST(ha, CFG_FLASH_ACC_SUPPORT)) {
                  if (ha->task_daemon_flags & FIRMWARE_UP) {
!                         for (timer = 3000; timer; timer--) {
!                                 if (ha->task_daemon_flags & ISP_ABORT_NEEDED) {
!                                         EL(ha, "ISP_ABORT_NEEDED done\n");
!                                         return (QL_ABORTED);
                                  }
!                                 rval = ql_flash_access(ha, FAC_SEMA_LOCK,
!                                     0, 0, NULL);
!                                 if (rval == QL_SUCCESS ||
!                                     rval == QL_FUNCTION_TIMEOUT) {
!                                         EL(ha, "lock status=%xh\n", rval);
!                                         break;
                                  }
+                                 delay(1);
+                         }
+ 
+                         if (rval == QL_SUCCESS &&
+                             (rval = ql_flash_access(ha, FAC_WRT_ENABLE, 0,
+                             0, NULL)) != QL_SUCCESS) {
+                                 EL(ha, "WRT_ENABLE status=%xh\n", rval);
+                                 (void) ql_flash_access(ha, FAC_SEMA_UNLOCK,
+                                     0, 0, NULL);
+                         }
                  } else {
+                         rval = QL_SUCCESS;
+                 }
+                 QL_PRINT_3(ha, "CFG_FLASH_ACC_SUPPORT done\n");
+                 return (rval);
+         } else {
                  /* Enable flash write. */
                  WRT32_IO_REG(ha, ctrl_status,
                      RD32_IO_REG(ha, ctrl_status) | ISP_FLASH_ENABLE);
                  RD32_IO_REG(ha, ctrl_status);   /* PCI Posting. */
          }
  
+         /* Sector/Block Protection Register Lock (SST, ST, ATMEL). */
+         (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x100 |
+             xp->fdesc.write_statusreg_cmd, xp->fdesc.write_enable_bits);
+ 
          /*
!          * Remove block write protection (SST and ST)
!          * Global unprotect sectors (ATMEL).
           */
          (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x100 |
              xp->fdesc.write_statusreg_cmd, xp->fdesc.write_enable_bits);
  
          if (xp->fdesc.unprotect_sector_cmd != 0) {
*** 11645,11655 ****
                      xp->fdesc.unprotect_sector_cmd, 0x00600f);
                  (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x300 |
                      xp->fdesc.unprotect_sector_cmd, 0x00800f);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (QL_SUCCESS);
  }
  
  /*
--- 12060,12070 ----
                      xp->fdesc.unprotect_sector_cmd, 0x00600f);
                  (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x300 |
                      xp->fdesc.unprotect_sector_cmd, 0x00800f);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (QL_SUCCESS);
  }
  
  /*
*** 11664,11695 ****
   */
  void
  ql_24xx_protect_flash(ql_adapter_state_t *vha)
  {
          int                     rval;
!         uint32_t                fdata;
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (CFG_IST(ha, CFG_CTRL_8021)) {
                  (void) ql_8021_rom_wrsr(ha, xp->fdesc.write_enable_bits);
                  rval = ql_8021_rom_wrsr(ha, xp->fdesc.write_disable_bits);
                  if (rval != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return;
          }
!         if (CFG_IST(ha, CFG_CTRL_81XX)) {
                  if (ha->task_daemon_flags & FIRMWARE_UP) {
!                         if ((rval = ql_flash_access(ha, FAC_WRT_PROTECT, 0, 0,
!                             0)) != QL_SUCCESS) {
!                                 EL(ha, "status=%xh\n", rval);
                          }
!                         QL_PRINT_3(CE_CONT, "(%d): 8100 done\n",
!                             ha->instance);
                          return;
                  }
          } else {
                  /* Enable flash write. */
                  WRT32_IO_REG(ha, ctrl_status,
--- 12079,12130 ----
   */
  void
  ql_24xx_protect_flash(ql_adapter_state_t *vha)
  {
          int                     rval;
!         uint32_t                fdata, timer;
          ql_adapter_state_t      *ha = vha->pha;
          ql_xioctl_t             *xp = ha->xioctl;
  
!         QL_PRINT_3(ha, "started\n");
  
!         if (CFG_IST(ha, CFG_CTRL_82XX)) {
                  (void) ql_8021_rom_wrsr(ha, xp->fdesc.write_enable_bits);
                  rval = ql_8021_rom_wrsr(ha, xp->fdesc.write_disable_bits);
                  if (rval != QL_SUCCESS) {
                          EL(ha, "8021 access error\n");
                  }
                  return;
          }
!         if (CFG_IST(ha, CFG_FLASH_ACC_SUPPORT)) {
                  if (ha->task_daemon_flags & FIRMWARE_UP) {
!                         for (timer = 3000; timer; timer--) {
!                                 if (ha->task_daemon_flags & ISP_ABORT_NEEDED) {
!                                         EL(ha, "ISP_ABORT_NEEDED done\n");
!                                         return;
                                  }
!                                 rval = ql_flash_access(ha, FAC_SEMA_LOCK,
!                                     0, 0, NULL);
!                                 if (rval == QL_SUCCESS ||
!                                     rval == QL_FUNCTION_TIMEOUT) {
!                                         if (rval != QL_SUCCESS) {
!                                                 EL(ha, "lock status=%xh\n",
!                                                     rval);
!                                         }
!                                         break;
!                                 }
!                                 delay(1);
!                         }
! 
!                         if (rval == QL_SUCCESS &&
!                             (rval = ql_flash_access(ha, FAC_WRT_PROTECT, 0,
!                             0, NULL)) != QL_SUCCESS) {
!                                 EL(ha, "protect status=%xh\n", rval);
!                                 (void) ql_flash_access(ha, FAC_SEMA_UNLOCK, 0,
!                                     0, NULL);
!                         }
!                         QL_PRINT_3(ha, "CFG_FLASH_ACC_SUPPORT done\n");
                          return;
                  }
          } else {
                  /* Enable flash write. */
                  WRT32_IO_REG(ha, ctrl_status,
*** 11703,11737 ****
           * Sector/Block Protection Register Lock (SST, ST, ATMEL).
           */
          if (xp->fdesc.protect_sector_cmd != 0) {
                  for (fdata = 0; fdata < 0x10; fdata++) {
                          (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR |
!                             0x330 | xp->fdesc.protect_sector_cmd, fdata);
                  }
!                 (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x330 |
                      xp->fdesc.protect_sector_cmd, 0x00400f);
!                 (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x330 |
                      xp->fdesc.protect_sector_cmd, 0x00600f);
!                 (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x330 |
                      xp->fdesc.protect_sector_cmd, 0x00800f);
- 
-                 /* TODO: ??? */
-                 (void) ql_24xx_write_flash(ha,
-                     FLASH_CONF_ADDR | 0x101, 0x80);
-         } else {
-                 (void) ql_24xx_write_flash(ha,
-                     FLASH_CONF_ADDR | 0x101, 0x9c);
          }
  
          /* Disable flash write. */
!         if (!(CFG_IST(ha, CFG_CTRL_81XX))) {
                  WRT32_IO_REG(ha, ctrl_status,
                      RD32_IO_REG(ha, ctrl_status) & ~ISP_FLASH_ENABLE);
                  RD32_IO_REG(ha, ctrl_status);   /* PCI Posting. */
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_dump_firmware
   *      Save RISC code state information.
--- 12138,12172 ----
           * Sector/Block Protection Register Lock (SST, ST, ATMEL).
           */
          if (xp->fdesc.protect_sector_cmd != 0) {
                  for (fdata = 0; fdata < 0x10; fdata++) {
                          (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR |
!                             0x300 | xp->fdesc.protect_sector_cmd, fdata);
                  }
!                 (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x300 |
                      xp->fdesc.protect_sector_cmd, 0x00400f);
!                 (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x300 |
                      xp->fdesc.protect_sector_cmd, 0x00600f);
!                 (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x300 |
                      xp->fdesc.protect_sector_cmd, 0x00800f);
          }
  
+         /* Remove Sector Protection Registers Locked (SPRL) bit. */
+         (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x100 |
+             xp->fdesc.write_statusreg_cmd, xp->fdesc.write_enable_bits);
+ 
+         (void) ql_24xx_write_flash(ha, FLASH_CONF_ADDR | 0x100 |
+             xp->fdesc.write_statusreg_cmd, xp->fdesc.write_disable_bits);
+ 
          /* Disable flash write. */
!         if (!CFG_IST(ha, CFG_FLASH_ACC_SUPPORT)) {
                  WRT32_IO_REG(ha, ctrl_status,
                      RD32_IO_REG(ha, ctrl_status) & ~ISP_FLASH_ENABLE);
                  RD32_IO_REG(ha, ctrl_status);   /* PCI Posting. */
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_dump_firmware
   *      Save RISC code state information.
*** 11743,11792 ****
   *      QL local function return status code.
   *
   * Context:
   *      Kernel context.
   */
! static int
  ql_dump_firmware(ql_adapter_state_t *vha)
  {
          int                     rval;
          clock_t                 timer = drv_usectohz(30000000);
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          QL_DUMP_LOCK(ha);
  
          if (ha->ql_dump_state & QL_DUMPING ||
              (ha->ql_dump_state & QL_DUMP_VALID &&
              !(ha->ql_dump_state & QL_DUMP_UPLOADED))) {
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
                  QL_DUMP_UNLOCK(ha);
                  return (QL_SUCCESS);
          }
  
          QL_DUMP_UNLOCK(ha);
  
!         ql_awaken_task_daemon(ha, NULL, DRIVER_STALL, 0);
  
-         /*
-          * Wait for all outstanding commands to complete
-          */
-         (void) ql_wait_outstanding(ha);
- 
          /* Dump firmware. */
          rval = ql_binary_fw_dump(ha, TRUE);
  
          /* Do abort to force restart. */
!         ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, DRIVER_STALL);
          EL(ha, "restarting, isp_abort_needed\n");
  
          /* Acquire task daemon lock. */
          TASK_DAEMON_LOCK(ha);
  
          /* Wait for suspension to end. */
!         while (ha->task_daemon_flags & QL_SUSPENDED) {
                  ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
  
                  /* 30 seconds from now */
                  if (cv_reltimedwait(&ha->cv_dr_suspended,
                      &ha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
--- 12178,12227 ----
   *      QL local function return status code.
   *
   * Context:
   *      Kernel context.
   */
! int
  ql_dump_firmware(ql_adapter_state_t *vha)
  {
          int                     rval;
          clock_t                 timer = drv_usectohz(30000000);
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(ha, "started\n");
  
          QL_DUMP_LOCK(ha);
  
          if (ha->ql_dump_state & QL_DUMPING ||
              (ha->ql_dump_state & QL_DUMP_VALID &&
              !(ha->ql_dump_state & QL_DUMP_UPLOADED))) {
!                 QL_PRINT_3(ha, "done\n");
                  QL_DUMP_UNLOCK(ha);
                  return (QL_SUCCESS);
          }
  
          QL_DUMP_UNLOCK(ha);
  
!         (void) ql_stall_driver(ha, 0);
  
          /* Dump firmware. */
+         if (CFG_IST(ha, CFG_CTRL_82XX)) {
+                 rval = ql_binary_fw_dump(ha, FALSE);
+         } else {
                  rval = ql_binary_fw_dump(ha, TRUE);
+         }
  
          /* Do abort to force restart. */
!         ql_restart_driver(ha);
!         ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
          EL(ha, "restarting, isp_abort_needed\n");
  
          /* Acquire task daemon lock. */
          TASK_DAEMON_LOCK(ha);
  
          /* Wait for suspension to end. */
!         while (DRIVER_SUSPENDED(ha)) {
                  ha->task_daemon_flags |= SUSPENDED_WAKEUP_FLG;
  
                  /* 30 seconds from now */
                  if (cv_reltimedwait(&ha->cv_dr_suspended,
                      &ha->task_daemon_mutex, timer, TR_CLOCK_TICK) == -1) {
*** 11802,11812 ****
          /* Release task daemon lock. */
          TASK_DAEMON_UNLOCK(ha);
  
          if (rval == QL_SUCCESS || rval == QL_DATA_EXISTS) {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          } else {
                  EL(ha, "failed, rval = %xh\n", rval);
          }
          return (rval);
  }
--- 12237,12247 ----
          /* Release task daemon lock. */
          TASK_DAEMON_UNLOCK(ha);
  
          if (rval == QL_SUCCESS || rval == QL_DATA_EXISTS) {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          } else {
                  EL(ha, "failed, rval = %xh\n", rval);
          }
          return (rval);
  }
*** 11826,11844 ****
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  int
  ql_binary_fw_dump(ql_adapter_state_t *vha, int lock_needed)
  {
          clock_t                 timer;
-         mbx_cmd_t               mc;
-         mbx_cmd_t               *mcp = &mc;
          int                     rval = QL_SUCCESS;
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (CFG_IST(ha, CFG_CTRL_8021)) {
                  EL(ha, "8021 not supported\n");
                  return (QL_NOT_SUPPORTED);
          }
  
          QL_DUMP_LOCK(ha);
--- 12261,12282 ----
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  int
  ql_binary_fw_dump(ql_adapter_state_t *vha, int lock_needed)
  {
+         uint32_t                cnt, index;
          clock_t                 timer;
          int                     rval = QL_SUCCESS;
          ql_adapter_state_t      *ha = vha->pha;
  
!         QL_PRINT_3(ha, "started\n");
  
!         ADAPTER_STATE_LOCK(ha);
!         ha->flags &= ~FW_DUMP_NEEDED;
!         ADAPTER_STATE_UNLOCK(ha);
! 
!         if (CFG_IST(ha, CFG_CTRL_82XX) && ha->md_capture_size == 0) {
                  EL(ha, "8021 not supported\n");
                  return (QL_NOT_SUPPORTED);
          }
  
          QL_DUMP_LOCK(ha);
*** 11855,11878 ****
          ha->ql_dump_state |= QL_DUMPING;
  
          QL_DUMP_UNLOCK(ha);
  
          if (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE)) {
- 
                  /* Insert Time Stamp */
                  rval = ql_fw_etrace(ha, &ha->fwexttracebuf,
!                     FTO_INSERT_TIME_STAMP);
                  if (rval != QL_SUCCESS) {
                          EL(ha, "f/w extended trace insert"
                              "time stamp failed: %xh\n", rval);
                  }
          }
  
          if (lock_needed == TRUE) {
                  /* Acquire mailbox register lock. */
                  MBX_REGISTER_LOCK(ha);
!                 timer = (ha->mcp->timeout + 2) * drv_usectohz(1000000);
  
                  /* Check for mailbox available, if not wait for signal. */
                  while (ha->mailbox_flags & MBX_BUSY_FLG) {
                          ha->mailbox_flags = (uint8_t)
                              (ha->mailbox_flags | MBX_WANT_FLG);
--- 12293,12315 ----
          ha->ql_dump_state |= QL_DUMPING;
  
          QL_DUMP_UNLOCK(ha);
  
          if (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE)) {
                  /* Insert Time Stamp */
                  rval = ql_fw_etrace(ha, &ha->fwexttracebuf,
!                     FTO_INSERT_TIME_STAMP, NULL);
                  if (rval != QL_SUCCESS) {
                          EL(ha, "f/w extended trace insert"
                              "time stamp failed: %xh\n", rval);
                  }
          }
  
          if (lock_needed == TRUE) {
                  /* Acquire mailbox register lock. */
                  MBX_REGISTER_LOCK(ha);
!                 timer = ((MAILBOX_TOV + 6) * drv_usectohz(1000000));
  
                  /* Check for mailbox available, if not wait for signal. */
                  while (ha->mailbox_flags & MBX_BUSY_FLG) {
                          ha->mailbox_flags = (uint8_t)
                              (ha->mailbox_flags | MBX_WANT_FLG);
*** 11896,11907 ****
                  }
  
                  /* Set busy flag. */
                  ha->mailbox_flags = (uint8_t)
                      (ha->mailbox_flags | MBX_BUSY_FLG);
-                 mcp->timeout = 120;
-                 ha->mcp = mcp;
  
                  /* Release mailbox register lock. */
                  MBX_REGISTER_UNLOCK(ha);
          }
  
--- 12333,12342 ----
*** 11909,11947 ****
          if (ha->ql_dump_ptr != NULL) {
                  kmem_free(ha->ql_dump_ptr, ha->ql_dump_size);
                  ha->ql_dump_ptr = NULL;
          }
  
!         if (CFG_IST(ha, CFG_CTRL_2422)) {
                  ha->ql_dump_size = (uint32_t)(sizeof (ql_24xx_fw_dump_t) +
                      ha->fw_ext_memory_size);
          } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
                  ha->ql_dump_size = (uint32_t)(sizeof (ql_25xx_fw_dump_t) +
!                     ha->fw_ext_memory_size);
          } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
                  ha->ql_dump_size = (uint32_t)(sizeof (ql_81xx_fw_dump_t) +
!                     ha->fw_ext_memory_size);
          } else {
                  ha->ql_dump_size = sizeof (ql_fw_dump_t);
          }
  
!         if ((ha->ql_dump_ptr = kmem_zalloc(ha->ql_dump_size, KM_NOSLEEP)) ==
!             NULL) {
                  rval = QL_MEMORY_ALLOC_FAILED;
          } else {
!                 if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
!                         rval = ql_2300_binary_fw_dump(ha, ha->ql_dump_ptr);
                  } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
!                         rval = ql_81xx_binary_fw_dump(ha, ha->ql_dump_ptr);
                  } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
!                         rval = ql_25xx_binary_fw_dump(ha, ha->ql_dump_ptr);
!                 } else if (CFG_IST(ha, CFG_CTRL_2422)) {
!                         rval = ql_24xx_binary_fw_dump(ha, ha->ql_dump_ptr);
                  } else {
!                         rval = ql_2200_binary_fw_dump(ha, ha->ql_dump_ptr);
                  }
          }
  
          /* Reset ISP chip. */
          ql_reset_chip(ha);
  
          QL_DUMP_LOCK(ha);
--- 12344,12419 ----
          if (ha->ql_dump_ptr != NULL) {
                  kmem_free(ha->ql_dump_ptr, ha->ql_dump_size);
                  ha->ql_dump_ptr = NULL;
          }
  
!         if (CFG_IST(ha, CFG_CTRL_24XX)) {
                  ha->ql_dump_size = (uint32_t)(sizeof (ql_24xx_fw_dump_t) +
                      ha->fw_ext_memory_size);
          } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
+                 cnt = ha->rsp_queues_cnt > 1 ? ha->req_q[0]->req_ring.size +
+                     ha->req_q[1]->req_ring.size : ha->req_q[0]->req_ring.size;
+                 index = ha->rsp_queues[0]->rsp_ring.size * ha->rsp_queues_cnt;
+ 
                  ha->ql_dump_size = (uint32_t)(sizeof (ql_25xx_fw_dump_t) +
!                     cnt + index + ha->fw_ext_memory_size +
!                     (ha->rsp_queues_cnt * 16));
! 
          } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
+                 cnt = ha->rsp_queues_cnt > 1 ? ha->req_q[0]->req_ring.size +
+                     ha->req_q[1]->req_ring.size : ha->req_q[0]->req_ring.size;
+                 index = ha->rsp_queues[0]->rsp_ring.size * ha->rsp_queues_cnt;
+ 
                  ha->ql_dump_size = (uint32_t)(sizeof (ql_81xx_fw_dump_t) +
!                     cnt + index + ha->fw_ext_memory_size +
!                     (ha->rsp_queues_cnt * 16));
! 
!         } else if (CFG_IST(ha, CFG_CTRL_83XX)) {
!                 cnt = ha->rsp_queues_cnt > 1 ? ha->req_q[0]->req_ring.size +
!                     ha->req_q[1]->req_ring.size : ha->req_q[0]->req_ring.size;
!                 index = ha->rsp_queues[0]->rsp_ring.size * ha->rsp_queues_cnt;
! 
!                 ha->ql_dump_size = (uint32_t)(sizeof (ql_83xx_fw_dump_t) +
!                     cnt + index + ha->fw_ext_memory_size +
!                     (ha->rsp_queues_cnt * 16));
!         } else if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                 ha->ql_dump_size = ha->md_capture_size;
          } else {
                  ha->ql_dump_size = sizeof (ql_fw_dump_t);
          }
  
!         if (CFG_IST(ha, CFG_CTRL_27XX)) {
!                 rval = ql_27xx_binary_fw_dump(ha);
!         } else {
!                 if ((ha->ql_dump_ptr =
!                     kmem_zalloc(ha->ql_dump_size, KM_NOSLEEP)) == NULL) {
                          rval = QL_MEMORY_ALLOC_FAILED;
                  } else {
!                         if (CFG_IST(ha, CFG_CTRL_2363)) {
!                                 rval = ql_2300_binary_fw_dump(ha,
!                                     ha->ql_dump_ptr);
                          } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
!                                 rval = ql_81xx_binary_fw_dump(ha,
!                                     ha->ql_dump_ptr);
!                         } else if (CFG_IST(ha, CFG_CTRL_83XX)) {
!                                 rval = ql_83xx_binary_fw_dump(ha,
!                                     ha->ql_dump_ptr);
                          } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
!                                 rval = ql_25xx_binary_fw_dump(ha,
!                                     ha->ql_dump_ptr);
!                         } else if (CFG_IST(ha, CFG_CTRL_24XX)) {
!                                 rval = ql_24xx_binary_fw_dump(ha,
!                                     ha->ql_dump_ptr);
!                         } else if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                                 (void) ql_8021_reset_fw(ha);
!                                 rval = QL_SUCCESS;
                          } else {
!                                 rval = ql_2200_binary_fw_dump(ha,
!                                     ha->ql_dump_ptr);
                          }
                  }
+         }
  
          /* Reset ISP chip. */
          ql_reset_chip(ha);
  
          QL_DUMP_LOCK(ha);
*** 11986,12007 ****
          caddr_t                 bp;
          int                     mbox_cnt;
          ql_adapter_state_t      *ha = vha->pha;
          ql_fw_dump_t            *fw = ha->ql_dump_ptr;
  
!         if (CFG_IST(ha, CFG_CTRL_2422)) {
                  return (ql_24xx_ascii_fw_dump(ha, bufp));
!         } else if (CFG_IST(ha, CFG_CTRL_2581)) {
!                 return (ql_2581_ascii_fw_dump(ha, bufp));
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (CFG_IST(ha, CFG_CTRL_2300)) {
                  (void) sprintf(bufp, "\nISP 2300IP ");
!         } else if (CFG_IST(ha, CFG_CTRL_6322)) {
!                 (void) sprintf(bufp, "\nISP 6322FLX ");
          } else {
                  (void) sprintf(bufp, "\nISP 2200IP ");
          }
  
          bp = bufp + strlen(bufp);
--- 12458,12487 ----
          caddr_t                 bp;
          int                     mbox_cnt;
          ql_adapter_state_t      *ha = vha->pha;
          ql_fw_dump_t            *fw = ha->ql_dump_ptr;
  
!         if (CFG_IST(ha, CFG_CTRL_24XX)) {
                  return (ql_24xx_ascii_fw_dump(ha, bufp));
!         } else if (CFG_IST(ha, CFG_CTRL_25XX)) {
!                 return (ql_25xx_ascii_fw_dump(ha, bufp));
!         } else if (CFG_IST(ha, CFG_CTRL_81XX)) {
!                 return (ql_81xx_ascii_fw_dump(ha, bufp));
!         } else if (CFG_IST(ha, CFG_CTRL_82XX)) {
!                 return (ql_8021_ascii_fw_dump(ha, bufp));
!         } else if (CFG_IST(ha, CFG_CTRL_83XX)) {
!                 return (ql_83xx_ascii_fw_dump(ha, bufp));
!         } else if (CFG_IST(ha, CFG_CTRL_27XX)) {
!                 return (ql_27xx_ascii_fw_dump(ha, bufp));
          }
  
!         QL_PRINT_3(ha, "started\n");
  
!         if (CFG_IST(ha, CFG_CTRL_23XX)) {
                  (void) sprintf(bufp, "\nISP 2300IP ");
!         } else if (CFG_IST(ha, CFG_CTRL_63XX)) {
!                 (void) sprintf(bufp, "\nISP 2322/6322FLX ");
          } else {
                  (void) sprintf(bufp, "\nISP 2200IP ");
          }
  
          bp = bufp + strlen(bufp);
*** 12017,12027 ****
                  }
                  (void) sprintf(bp, "%04x  ", fw->pbiu_reg[cnt]);
                  bp = bp + 6;
          }
  
!         if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
                  (void) strcat(bufp, "\n\nReqQ-RspQ-Risc2Host Status "
                      "registers:");
                  bp = bufp + strlen(bufp);
                  for (cnt = 0; cnt < sizeof (fw->risc_host_reg) / 2; cnt++) {
                          if (cnt % 8 == 0) {
--- 12497,12507 ----
                  }
                  (void) sprintf(bp, "%04x  ", fw->pbiu_reg[cnt]);
                  bp = bp + 6;
          }
  
!         if (CFG_IST(ha, CFG_CTRL_2363)) {
                  (void) strcat(bufp, "\n\nReqQ-RspQ-Risc2Host Status "
                      "registers:");
                  bp = bufp + strlen(bufp);
                  for (cnt = 0; cnt < sizeof (fw->risc_host_reg) / 2; cnt++) {
                          if (cnt % 8 == 0) {
*** 12032,12051 ****
                  }
          }
  
          (void) strcat(bp, "\n\nMailbox Registers:");
          bp = bufp + strlen(bufp);
!         mbox_cnt = (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) ? 16 : 8;
          for (cnt = 0; cnt < mbox_cnt; cnt++) {
                  if (cnt % 8 == 0) {
                          *bp++ = '\n';
                  }
                  (void) sprintf(bp, "%04x  ", fw->mailbox_reg[cnt]);
                  bp = bp + 6;
          }
  
!         if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
                  (void) strcat(bp, "\n\nAuto Request Response DMA Registers:");
                  bp = bufp + strlen(bufp);
                  for (cnt = 0; cnt < sizeof (fw->resp_dma_reg) / 2; cnt++) {
                          if (cnt % 8 == 0) {
                                  *bp++ = '\n';
--- 12512,12531 ----
                  }
          }
  
          (void) strcat(bp, "\n\nMailbox Registers:");
          bp = bufp + strlen(bufp);
!         mbox_cnt = CFG_IST(ha, CFG_CTRL_2363) ? 16 : 8;
          for (cnt = 0; cnt < mbox_cnt; cnt++) {
                  if (cnt % 8 == 0) {
                          *bp++ = '\n';
                  }
                  (void) sprintf(bp, "%04x  ", fw->mailbox_reg[cnt]);
                  bp = bp + 6;
          }
  
!         if (CFG_IST(ha, CFG_CTRL_2363)) {
                  (void) strcat(bp, "\n\nAuto Request Response DMA Registers:");
                  bp = bufp + strlen(bufp);
                  for (cnt = 0; cnt < sizeof (fw->resp_dma_reg) / 2; cnt++) {
                          if (cnt % 8 == 0) {
                                  *bp++ = '\n';
*** 12156,12167 ****
          }
  
          (void) strcat(bp, "\n\nFrame Buffer Hardware Registers:");
          bp = bufp + strlen(bufp);
          for (cnt = 0; cnt < sizeof (fw->frame_buf_hdw_reg) / 2; cnt++) {
!                 if ((cnt == 16) && ((CFG_IST(ha, (CFG_CTRL_2300 |
!                     CFG_CTRL_6322)) == 0))) {
                          break;
                  }
                  if (cnt % 8 == 0) {
                          *bp++ = '\n';
                  }
--- 12636,12646 ----
          }
  
          (void) strcat(bp, "\n\nFrame Buffer Hardware Registers:");
          bp = bufp + strlen(bufp);
          for (cnt = 0; cnt < sizeof (fw->frame_buf_hdw_reg) / 2; cnt++) {
!                 if (cnt == 16 && !CFG_IST(ha, CFG_CTRL_2363)) {
                          break;
                  }
                  if (cnt % 8 == 0) {
                          *bp++ = '\n';
                  }
*** 12187,12197 ****
                  }
                  (void) sprintf(bp, "%04x  ", fw->fpm_b1_reg[cnt]);
                  bp = bp + 6;
          }
  
!         if (CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) {
                  (void) strcat(bp, "\n\nCode RAM Dump:");
                  bp = bufp + strlen(bufp);
                  for (cnt = 0; cnt < sizeof (fw->risc_ram) / 2; cnt++) {
                          if (cnt % 8 == 0) {
                                  (void) sprintf(bp, "\n%05x: ", cnt + 0x0800);
--- 12666,12676 ----
                  }
                  (void) sprintf(bp, "%04x  ", fw->fpm_b1_reg[cnt]);
                  bp = bp + 6;
          }
  
!         if (CFG_IST(ha, CFG_CTRL_2363)) {
                  (void) strcat(bp, "\n\nCode RAM Dump:");
                  bp = bufp + strlen(bufp);
                  for (cnt = 0; cnt < sizeof (fw->risc_ram) / 2; cnt++) {
                          if (cnt % 8 == 0) {
                                  (void) sprintf(bp, "\n%05x: ", cnt + 0x0800);
*** 12260,12270 ****
                  bp += strlen(bp);
          }
  
          (void) sprintf(bp, "\n");
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (strlen(bufp));
  }
  
  /*
--- 12739,12749 ----
                  bp += strlen(bp);
          }
  
          (void) sprintf(bp, "\n");
  
!         QL_PRINT_10(ha, "done, size=0x%x\n", strlen(bufp));
  
          return (strlen(bufp));
  }
  
  /*
*** 12286,12296 ****
  {
          uint32_t                cnt;
          caddr_t                 bp = bufp;
          ql_24xx_fw_dump_t       *fw = ha->ql_dump_ptr;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          (void) sprintf(bp, "ISP FW Version %d.%02d.%02d Attributes %X\n",
              ha->fw_major_version, ha->fw_minor_version,
              ha->fw_subminor_version, ha->fw_attributes);
          bp += strlen(bp);
--- 12765,12775 ----
  {
          uint32_t                cnt;
          caddr_t                 bp = bufp;
          ql_24xx_fw_dump_t       *fw = ha->ql_dump_ptr;
  
!         QL_PRINT_3(ha, "started\n");
  
          (void) sprintf(bp, "ISP FW Version %d.%02d.%02d Attributes %X\n",
              ha->fw_major_version, ha->fw_minor_version,
              ha->fw_subminor_version, ha->fw_attributes);
          bp += strlen(bp);
*** 12674,12691 ****
          (void) sprintf(bp, "\n\n");
          bp += strlen(bp);
  
          cnt = (uint32_t)((uintptr_t)bp - (uintptr_t)bufp);
  
!         QL_PRINT_3(CE_CONT, "(%d): done=%xh\n", ha->instance, cnt);
  
          return (cnt);
  }
  
  /*
!  * ql_2581_ascii_fw_dump
!  *      Converts ISP25xx or ISP81xx firmware binary dump to ascii.
   *
   * Input:
   *      ha = adapter state pointer.
   *      bptr = buffer pointer.
   *
--- 13153,13170 ----
          (void) sprintf(bp, "\n\n");
          bp += strlen(bp);
  
          cnt = (uint32_t)((uintptr_t)bp - (uintptr_t)bufp);
  
!         QL_PRINT_10(ha, "done=%xh\n", cnt);
  
          return (cnt);
  }
  
  /*
!  * ql_25xx_ascii_fw_dump
!  *      Converts ISP25xx firmware binary dump to ascii.
   *
   * Input:
   *      ha = adapter state pointer.
   *      bptr = buffer pointer.
   *
*** 12694,12720 ****
   *
   * Context:
   *      Kernel context.
   */
  static size_t
! ql_2581_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
  {
!         uint32_t                cnt;
!         uint32_t                cnt1;
          caddr_t                 bp = bufp;
          ql_25xx_fw_dump_t       *fw = ha->ql_dump_ptr;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          (void) sprintf(bp, "\nISP FW Version %d.%02d.%02d Attributes %X\n",
              ha->fw_major_version, ha->fw_minor_version,
              ha->fw_subminor_version, ha->fw_attributes);
          bp += strlen(bp);
  
          (void) sprintf(bp, "\nR2H Status Register\n%08x\n", fw->r2h_status);
          bp += strlen(bp);
  
          (void) sprintf(bp, "\nHostRisc Registers");
          bp += strlen(bp);
          for (cnt = 0; cnt < sizeof (fw->hostrisc_reg) / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp++, "\n");
--- 13173,13205 ----
   *
   * Context:
   *      Kernel context.
   */
  static size_t
! ql_25xx_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
  {
!         uint32_t                cnt, cnt1, *dp, *dp2;
          caddr_t                 bp = bufp;
          ql_25xx_fw_dump_t       *fw = ha->ql_dump_ptr;
  
!         QL_PRINT_3(ha, "started\n");
  
          (void) sprintf(bp, "\nISP FW Version %d.%02d.%02d Attributes %X\n",
              ha->fw_major_version, ha->fw_minor_version,
              ha->fw_subminor_version, ha->fw_attributes);
          bp += strlen(bp);
  
+         (void) sprintf(bp, "\nHCCR Register\n%08x\n", fw->hccr);
+         bp += strlen(bp);
+ 
          (void) sprintf(bp, "\nR2H Status Register\n%08x\n", fw->r2h_status);
          bp += strlen(bp);
  
+         (void) sprintf(bp, "\nAER Uncorrectable Error Status Register\n%08x\n",
+             fw->aer_ues);
+         bp += strlen(bp);
+ 
          (void) sprintf(bp, "\nHostRisc Registers");
          bp += strlen(bp);
          for (cnt = 0; cnt < sizeof (fw->hostrisc_reg) / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp++, "\n");
*** 13017,13029 ****
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n\nFPM Hardware Registers");
          bp += strlen(bp);
!         cnt1 = CFG_IST(ha, CFG_CTRL_81XX) ?
!             (uint32_t)(sizeof (((ql_81xx_fw_dump_t *)(fw))->fpm_hdw_reg)) :
!             (uint32_t)(sizeof (fw->fpm_hdw_reg));
          for (cnt = 0; cnt < cnt1 / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp++, "\n");
                  }
                  (void) sprintf(bp, "%08x ", fw->fpm_hdw_reg[cnt]);
--- 13502,13512 ----
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n\nFPM Hardware Registers");
          bp += strlen(bp);
!         cnt1 = sizeof (fw->fpm_hdw_reg);
          for (cnt = 0; cnt < cnt1 / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp++, "\n");
                  }
                  (void) sprintf(bp, "%08x ", fw->fpm_hdw_reg[cnt]);
*** 13030,13042 ****
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n\nFB Hardware Registers");
          bp += strlen(bp);
!         cnt1 = CFG_IST(ha, CFG_CTRL_81XX) ?
!             (uint32_t)(sizeof (((ql_81xx_fw_dump_t *)(fw))->fb_hdw_reg)) :
!             (uint32_t)(sizeof (fw->fb_hdw_reg));
          for (cnt = 0; cnt < cnt1 / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp++, "\n");
                  }
                  (void) sprintf(bp, "%08x ", fw->fb_hdw_reg[cnt]);
--- 13513,13523 ----
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n\nFB Hardware Registers");
          bp += strlen(bp);
!         cnt1 = sizeof (fw->fb_hdw_reg);
          for (cnt = 0; cnt < cnt1 / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp++, "\n");
                  }
                  (void) sprintf(bp, "%08x ", fw->fb_hdw_reg[cnt]);
*** 13054,13097 ****
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n\nExternal Memory");
          bp += strlen(bp);
          for (cnt = 0; cnt < ha->fw_ext_memory_size / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp, "\n%08x: ", cnt + 0x100000);
                          bp += 11;
                  }
!                 (void) sprintf(bp, "%08x ", fw->ext_mem[cnt]);
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n[<==END] ISP Debug Dump");
          bp += strlen(bp);
  
!         (void) sprintf(bp, "\n\nRequest Queue");
          bp += strlen(bp);
!         for (cnt = 0; cnt < REQUEST_QUEUE_SIZE / 4; cnt++) {
                  if (cnt % 8 == 0) {
!                         (void) sprintf(bp, "\n%08x: ", cnt);
                          bp += strlen(bp);
                  }
!                 (void) sprintf(bp, "%08x ", fw->req_q[cnt]);
                  bp += strlen(bp);
          }
  
!         (void) sprintf(bp, "\n\nResponse Queue");
          bp += strlen(bp);
!         for (cnt = 0; cnt < RESPONSE_QUEUE_SIZE / 4; cnt++) {
                  if (cnt % 8 == 0) {
!                         (void) sprintf(bp, "\n%08x: ", cnt);
                          bp += strlen(bp);
                  }
!                 (void) sprintf(bp, "%08x ", fw->rsp_q[cnt]);
                  bp += strlen(bp);
          }
  
          if (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE) &&
              (ha->fwexttracebuf.bp != NULL)) {
                  uint32_t cnt_b = 0;
                  uint64_t w64 = (uintptr_t)ha->fwexttracebuf.bp;
  
--- 13535,14097 ----
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n\nExternal Memory");
          bp += strlen(bp);
+         dp = (uint32_t *)((caddr_t)fw->req_rsp_ext_mem + fw->req_q_size[0] +
+             fw->req_q_size[1] + fw->rsp_q_size + (ha->rsp_queues_cnt * 16));
          for (cnt = 0; cnt < ha->fw_ext_memory_size / 4; cnt++) {
                  if (cnt % 8 == 0) {
                          (void) sprintf(bp, "\n%08x: ", cnt + 0x100000);
                          bp += 11;
                  }
!                 (void) sprintf(bp, "%08x ", *dp++);
                  bp += 9;
          }
  
          (void) sprintf(bp, "\n[<==END] ISP Debug Dump");
          bp += strlen(bp);
  
!         dp = fw->req_rsp_ext_mem + (ha->rsp_queues_cnt * 4);
!         for (cnt = 0; cnt < 2 && fw->req_q_size[cnt]; cnt++) {
!                 dp2 = dp;
!                 for (cnt1 = 0; cnt1 < fw->req_q_size[cnt] / 4; cnt1++) {
!                         if (*dp2++) {
!                                 break;
!                         }
!                 }
!                 if (cnt1 == fw->req_q_size[cnt] / 4) {
!                         dp = dp2;
!                         continue;
!                 }
!                 (void) sprintf(bp, "\n\nRequest Queue\nQueue %d:", cnt);
                  bp += strlen(bp);
!                 for (cnt1 = 0; cnt1 < fw->req_q_size[cnt] / 4; cnt1++) {
!                         if (cnt1 % 8 == 0) {
!                                 (void) sprintf(bp, "\n%08x: ", cnt1);
!                                 bp += strlen(bp);
!                         }
!                         (void) sprintf(bp, "%08x ", *dp++);
!                         bp += strlen(bp);
!                 }
!         }
! 
!         for (cnt = 0; cnt < ha->rsp_queues_cnt && cnt < 16; cnt++) {
!                 dp2 = dp;
!                 for (cnt1 = 0; cnt1 < ha->rsp_queues[cnt]->rsp_ring.size / 4;
!                     cnt1++) {
!                         if (*dp2++) {
!                                 break;
!                         }
!                 }
!                 if (cnt1 == ha->rsp_queues[cnt]->rsp_ring.size / 4) {
!                         dp = dp2;
!                         continue;
!                 }
!                 (void) sprintf(bp, "\n\nResponse Queue\nQueue %d:", cnt);
!                 bp += strlen(bp);
!                 for (cnt1 = 0; cnt1 < ha->rsp_queues[cnt]->rsp_ring.size / 4;
!                     cnt1++) {
!                         if (cnt1 % 8 == 0) {
!                                 (void) sprintf(bp, "\n%08x: ", cnt1);
!                                 bp += strlen(bp);
!                         }
!                         (void) sprintf(bp, "%08x ", *dp++);
!                         bp += strlen(bp);
!                 }
!         }
! 
!         if (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE) &&
!             (ha->fwexttracebuf.bp != NULL)) {
!                 uint32_t cnt_b = 0;
!                 uint64_t w64 = (uintptr_t)ha->fwexttracebuf.bp;
! 
!                 (void) sprintf(bp, "\n\nExtended Trace Buffer Memory");
!                 bp += strlen(bp);
!                 /* show data address as a byte address, data as long words */
!                 for (cnt = 0; cnt < FWEXTSIZE / 4; cnt++) {
!                         cnt_b = cnt * 4;
!                         if (cnt_b % 32 == 0) {
!                                 (void) sprintf(bp, "\n%08x: ",
!                                     (int)(w64 + cnt_b));
!                                 bp += 11;
!                         }
!                         (void) sprintf(bp, "%08x ", fw->ext_trace_buf[cnt]);
!                         bp += 9;
!                 }
!         }
! 
!         if (CFG_IST(ha, CFG_ENABLE_FWFCETRACE) &&
!             (ha->fwfcetracebuf.bp != NULL)) {
!                 uint32_t cnt_b = 0;
!                 uint64_t w64 = (uintptr_t)ha->fwfcetracebuf.bp;
! 
!                 (void) sprintf(bp, "\n\nFC Event Trace Buffer Memory");
!                 bp += strlen(bp);
!                 /* show data address as a byte address, data as long words */
!                 for (cnt = 0; cnt < FWFCESIZE / 4; cnt++) {
!                         cnt_b = cnt * 4;
!                         if (cnt_b % 32 == 0) {
!                                 (void) sprintf(bp, "\n%08x: ",
!                                     (int)(w64 + cnt_b));
!                                 bp += 11;
!                         }
!                         (void) sprintf(bp, "%08x ", fw->fce_trace_buf[cnt]);
!                         bp += 9;
!                 }
!         }
! 
!         (void) sprintf(bp, "\n\n");
!         bp += strlen(bp);
! 
!         cnt = (uint32_t)((uintptr_t)bp - (uintptr_t)bufp);
! 
!         QL_PRINT_10(ha, "done=%xh\n", cnt);
! 
!         return (cnt);
! }
! 
! /*
!  * ql_81xx_ascii_fw_dump
!  *      Converts ISP81xx firmware binary dump to ascii.
!  *
!  * Input:
!  *      ha = adapter state pointer.
!  *      bptr = buffer pointer.
!  *
!  * Returns:
!  *      Amount of data buffer used.
!  *
!  * Context:
!  *      Kernel context.
!  */
! static size_t
! ql_81xx_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
! {
!         uint32_t                cnt, cnt1, *dp, *dp2;
!         caddr_t                 bp = bufp;
!         ql_81xx_fw_dump_t       *fw = ha->ql_dump_ptr;
! 
!         QL_PRINT_3(ha, "started\n");
! 
!         (void) sprintf(bp, "\nISP FW Version %d.%02d.%02d Attributes %X\n",
!             ha->fw_major_version, ha->fw_minor_version,
!             ha->fw_subminor_version, ha->fw_attributes);
!         bp += strlen(bp);
! 
!         (void) sprintf(bp, "\nHCCR Register\n%08x\n", fw->hccr);
!         bp += strlen(bp);
! 
!         (void) sprintf(bp, "\nR2H Status Register\n%08x\n", fw->r2h_status);
!         bp += strlen(bp);
! 
!         (void) sprintf(bp, "\nAER Uncorrectable Error Status Register\n%08x\n",
!             fw->aer_ues);
!         bp += strlen(bp);
! 
!         (void) sprintf(bp, "\nHostRisc Registers");
!         bp += strlen(bp);
!         for (cnt = 0; cnt < sizeof (fw->hostrisc_reg) / 4; cnt++) {
                  if (cnt % 8 == 0) {
!                         (void) sprintf(bp++, "\n");
!                 }
!                 (void) sprintf(bp, "%08x ", fw->hostrisc_reg[cnt]);
!                 bp += 9;
!         }
! 
!         (void) sprintf(bp, "\n\nPCIe Registers");
          bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->pcie_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
                  }
!                 (void) sprintf(bp, "%08x ", fw->pcie_reg[cnt]);
!                 bp += 9;
!         }
! 
!         (void) strcat(bp, "\n\nHost Interface Registers");
          bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->host_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
                  }
+                 (void) sprintf(bp, "%08x ", fw->host_reg[cnt]);
+                 bp += 9;
+         }
  
!         (void) sprintf(bufp + strlen(bufp), "\n\nShadow Registers");
          bp += strlen(bp);
!         for (cnt = 0; cnt < sizeof (fw->shadow_reg) / 4; cnt++) {
                  if (cnt % 8 == 0) {
!                         (void) sprintf(bp++, "\n");
!                 }
!                 (void) sprintf(bp, "%08x ", fw->shadow_reg[cnt]);
!                 bp += 9;
!         }
! 
!         (void) sprintf(bufp + strlen(bufp), "\n\nRISC IO Register\n%08x",
!             fw->risc_io);
          bp += strlen(bp);
+ 
+         (void) sprintf(bp, "\n\nMailbox Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->mailbox_reg) / 2; cnt++) {
+                 if (cnt % 16 == 0) {
+                         (void) sprintf(bp++, "\n");
                  }
!                 (void) sprintf(bp, "%04x ", fw->mailbox_reg[cnt]);
!                 bp += 5;
!         }
! 
!         (void) sprintf(bp, "\n\nXSEQ GP Registers");
          bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xseq_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
                  }
+                 (void) sprintf(bp, "%08x ", fw->xseq_gp_reg[cnt]);
+                 bp += 9;
+         }
  
+         (void) sprintf(bp, "\n\nXSEQ-0 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xseq_0_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xseq_0_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nXSEQ-1 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xseq_1_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xseq_1_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRSEQ GP Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->rseq_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->rseq_gp_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRSEQ-0 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->rseq_0_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->rseq_0_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRSEQ-1 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->rseq_1_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->rseq_1_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRSEQ-2 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->rseq_2_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->rseq_2_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nASEQ GP Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->aseq_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->aseq_gp_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nASEQ-0 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->aseq_0_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->aseq_0_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nASEQ-1 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->aseq_1_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->aseq_1_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nASEQ-2 Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->aseq_2_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->aseq_2_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nCommand DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->cmd_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->cmd_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRequest0 Queue DMA Channel Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->req0_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->req0_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nResponse0 Queue DMA Channel Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->resp0_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->resp0_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRequest1 Queue DMA Channel Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->req1_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->req1_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nXMT0 Data DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xmt0_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xmt0_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nXMT1 Data DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xmt1_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xmt1_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nXMT2 Data DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xmt2_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xmt2_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nXMT3 Data DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xmt3_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xmt3_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nXMT4 Data DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xmt4_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xmt4_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nXMT Data DMA Common Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->xmt_data_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->xmt_data_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRCV Thread 0 Data DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->rcvt0_data_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->rcvt0_data_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRCV Thread 1 Data DMA Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->rcvt1_data_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->rcvt1_data_dma_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nRISC GP Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->risc_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->risc_gp_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nLMC Registers");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->lmc_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->lmc_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nFPM Hardware Registers");
+         bp += strlen(bp);
+         cnt1 = sizeof (fw->fpm_hdw_reg);
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->fpm_hdw_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nFB Hardware Registers");
+         bp += strlen(bp);
+         cnt1 = sizeof (fw->fb_hdw_reg);
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp++, "\n");
+                 }
+                 (void) sprintf(bp, "%08x ", fw->fb_hdw_reg[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nCode RAM");
+         bp += strlen(bp);
+         for (cnt = 0; cnt < sizeof (fw->code_ram) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp, "\n%08x: ", cnt + 0x20000);
+                         bp += 11;
+                 }
+                 (void) sprintf(bp, "%08x ", fw->code_ram[cnt]);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n\nExternal Memory");
+         bp += strlen(bp);
+         dp = (uint32_t *)((caddr_t)fw->req_rsp_ext_mem + fw->req_q_size[0] +
+             fw->req_q_size[1] + fw->rsp_q_size + (ha->rsp_queues_cnt * 16));
+         for (cnt = 0; cnt < ha->fw_ext_memory_size / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) sprintf(bp, "\n%08x: ", cnt + 0x100000);
+                         bp += 11;
+                 }
+                 (void) sprintf(bp, "%08x ", *dp++);
+                 bp += 9;
+         }
+ 
+         (void) sprintf(bp, "\n[<==END] ISP Debug Dump");
+         bp += strlen(bp);
+ 
+         dp = fw->req_rsp_ext_mem + (ha->rsp_queues_cnt * 4);
+         for (cnt = 0; cnt < 2 && fw->req_q_size[cnt]; cnt++) {
+                 dp2 = dp;
+                 for (cnt1 = 0; cnt1 < fw->req_q_size[cnt] / 4; cnt1++) {
+                         if (*dp2++) {
+                                 break;
+                         }
+                 }
+                 if (cnt1 == fw->req_q_size[cnt] / 4) {
+                         dp = dp2;
+                         continue;
+                 }
+                 (void) sprintf(bp, "\n\nRequest Queue\nQueue %d:", cnt);
+                 bp += strlen(bp);
+                 for (cnt1 = 0; cnt1 < fw->req_q_size[cnt] / 4; cnt1++) {
+                         if (cnt1 % 8 == 0) {
+                                 (void) sprintf(bp, "\n%08x: ", cnt1);
+                                 bp += strlen(bp);
+                         }
+                         (void) sprintf(bp, "%08x ", *dp++);
+                         bp += strlen(bp);
+                 }
+         }
+ 
+         for (cnt = 0; cnt < ha->rsp_queues_cnt && cnt < 16; cnt++) {
+                 dp2 = dp;
+                 for (cnt1 = 0; cnt1 < ha->rsp_queues[cnt]->rsp_ring.size / 4;
+                     cnt1++) {
+                         if (*dp2++) {
+                                 break;
+                         }
+                 }
+                 if (cnt1 == ha->rsp_queues[cnt]->rsp_ring.size / 4) {
+                         dp = dp2;
+                         continue;
+                 }
+                 (void) sprintf(bp, "\n\nResponse Queue\nQueue %d:", cnt);
+                 bp += strlen(bp);
+                 for (cnt1 = 0; cnt1 < ha->rsp_queues[cnt]->rsp_ring.size / 4;
+                     cnt1++) {
+                         if (cnt1 % 8 == 0) {
+                                 (void) sprintf(bp, "\n%08x: ", cnt1);
+                                 bp += strlen(bp);
+                         }
+                         (void) sprintf(bp, "%08x ", *dp++);
+                         bp += strlen(bp);
+                 }
+         }
+ 
          if (CFG_IST(ha, CFG_ENABLE_FWEXTTRACE) &&
              (ha->fwexttracebuf.bp != NULL)) {
                  uint32_t cnt_b = 0;
                  uint64_t w64 = (uintptr_t)ha->fwexttracebuf.bp;
  
*** 13133,13148 ****
          (void) sprintf(bp, "\n\n");
          bp += strlen(bp);
  
          cnt = (uint32_t)((uintptr_t)bp - (uintptr_t)bufp);
  
!         QL_PRINT_3(CE_CONT, "(%d): done=%xh\n", ha->instance, cnt);
  
          return (cnt);
  }
  
  /*
   * ql_2200_binary_fw_dump
   *
   * Input:
   *      ha:     adapter state pointer.
   *      fw:     firmware dump context pointer.
--- 14133,14191 ----
          (void) sprintf(bp, "\n\n");
          bp += strlen(bp);
  
          cnt = (uint32_t)((uintptr_t)bp - (uintptr_t)bufp);
  
!         QL_PRINT_10(ha, "done=%xh\n", cnt);
  
          return (cnt);
  }
  
  /*
+  * ql_8021_ascii_fw_dump
+  *      Converts ISP8021 firmware binary dump to ascii.
+  *
+  * Input:
+  *      ha = adapter state pointer.
+  *      bptr = buffer pointer.
+  *
+  * Returns:
+  *      Amount of data buffer used.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static size_t
+ ql_8021_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
+ {
+         uint32_t        cnt;
+         caddr_t         bp = bufp;
+         uint8_t         *fw = ha->ql_dump_ptr;
+ 
+         /*
+          * 2 ascii bytes per binary byte + a space and
+          * a newline every 16 binary bytes
+          */
+         cnt = 0;
+         while (cnt < ha->ql_dump_size) {
+                 (void) sprintf(bp, "%02x ", *fw++);
+                 bp += strlen(bp);
+                 if (++cnt % 16 == 0) {
+                         (void) sprintf(bp, "\n");
+                         bp += strlen(bp);
+                 }
+         }
+         if (cnt % 16 != 0) {
+                 (void) sprintf(bp, "\n");
+                 bp += strlen(bp);
+         }
+         cnt = (uint32_t)((uintptr_t)bp - (uintptr_t)bufp);
+         QL_PRINT_10(ha, "done=%xh\n", cnt);
+         return (cnt);
+ }
+ 
+ /*
   * ql_2200_binary_fw_dump
   *
   * Input:
   *      ha:     adapter state pointer.
   *      fw:     firmware dump context pointer.
*** 13161,13177 ****
          clock_t         timer;
          mbx_cmd_t       mc;
          mbx_cmd_t       *mcp = &mc;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Disable ISP interrupts. */
!         WRT16_IO_REG(ha, ictrl, 0);
!         ADAPTER_STATE_LOCK(ha);
!         ha->flags &= ~INTERRUPTS_ENABLED;
!         ADAPTER_STATE_UNLOCK(ha);
  
          /* Release mailbox registers. */
          WRT16_IO_REG(ha, semaphore, 0);
  
          /* Pause RISC. */
--- 14204,14217 ----
          clock_t         timer;
          mbx_cmd_t       mc;
          mbx_cmd_t       *mcp = &mc;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Disable ISP interrupts. */
!         ql_disable_intr(ha);
  
          /* Release mailbox registers. */
          WRT16_IO_REG(ha, semaphore, 0);
  
          /* Pause RISC. */
*** 13270,13280 ****
                  /* Release RISC module. */
                  WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
  
                  /* Wait for RISC to recover from reset. */
                  timer = 30000;
!                 while (RD16_IO_REG(ha, mailbox_out[0]) == MBS_BUSY) {
                          if (timer-- != 0) {
                                  drv_usecwait(MILLISEC);
                          } else {
                                  rval = QL_FUNCTION_TIMEOUT;
                                  break;
--- 14310,14320 ----
                  /* Release RISC module. */
                  WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
  
                  /* Wait for RISC to recover from reset. */
                  timer = 30000;
!                 while (RD16_IO_REG(ha, mailbox_out[0]) == MBS_ROM_BUSY) {
                          if (timer-- != 0) {
                                  drv_usecwait(MILLISEC);
                          } else {
                                  rval = QL_FUNCTION_TIMEOUT;
                                  break;
*** 13344,13354 ****
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 14384,14394 ----
                                  break;
                          }
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 13368,13384 ****
  ql_2300_binary_fw_dump(ql_adapter_state_t *ha, ql_fw_dump_t *fw)
  {
          clock_t timer;
          int     rval = QL_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Disable ISP interrupts. */
!         WRT16_IO_REG(ha, ictrl, 0);
!         ADAPTER_STATE_LOCK(ha);
!         ha->flags &= ~INTERRUPTS_ENABLED;
!         ADAPTER_STATE_UNLOCK(ha);
  
          /* Release mailbox registers. */
          WRT16_IO_REG(ha, semaphore, 0);
  
          /* Pause RISC. */
--- 14408,14421 ----
  ql_2300_binary_fw_dump(ql_adapter_state_t *ha, ql_fw_dump_t *fw)
  {
          clock_t timer;
          int     rval = QL_SUCCESS;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Disable ISP interrupts. */
!         ql_disable_intr(ha);
  
          /* Release mailbox registers. */
          WRT16_IO_REG(ha, semaphore, 0);
  
          /* Pause RISC. */
*** 13483,13493 ****
                  /* Release RISC module. */
                  WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
  
                  /* Wait for RISC to recover from reset. */
                  timer = 30000;
!                 while (RD16_IO_REG(ha, mailbox_out[0]) == MBS_BUSY) {
                          if (timer-- != 0) {
                                  drv_usecwait(MILLISEC);
                          } else {
                                  rval = QL_FUNCTION_TIMEOUT;
                                  break;
--- 14520,14530 ----
                  /* Release RISC module. */
                  WRT16_IO_REG(ha, hccr, HC_RELEASE_RISC);
  
                  /* Wait for RISC to recover from reset. */
                  timer = 30000;
!                 while (RD16_IO_REG(ha, mailbox_out[0]) == MBS_ROM_BUSY) {
                          if (timer-- != 0) {
                                  drv_usecwait(MILLISEC);
                          } else {
                                  rval = QL_FUNCTION_TIMEOUT;
                                  break;
*** 13509,13519 ****
          /* Get DATA SRAM. */
          if (rval == QL_SUCCESS) {
                  rval = ql_read_risc_ram(ha, 0x10800, 0xf800, fw->data_ram);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 14546,14556 ----
          /* Get DATA SRAM. */
          if (rval == QL_SUCCESS) {
                  rval = ql_read_risc_ram(ha, 0x10800, 0xf800, fw->data_ram);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 13535,13552 ****
          uint32_t        *reg32;
          void            *bp;
          clock_t         timer;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          fw->hccr = RD32_IO_REG(ha, hccr);
  
          /* Pause RISC. */
          if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
                  /* Disable ISP interrupts. */
!                 WRT16_IO_REG(ha, ictrl, 0);
  
                  WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
                  for (timer = 30000;
                      (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0 &&
                      rval == QL_SUCCESS; timer--) {
--- 14572,14589 ----
          uint32_t        *reg32;
          void            *bp;
          clock_t         timer;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(ha, "started\n");
  
          fw->hccr = RD32_IO_REG(ha, hccr);
  
          /* Pause RISC. */
          if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
                  /* Disable ISP interrupts. */
!                 ql_disable_intr(ha);
  
                  WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
                  for (timer = 30000;
                      (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0 &&
                      rval == QL_SUCCESS; timer--) {
*** 13562,13576 ****
                  /* Host interface registers. */
                  (void) ql_read_regs(ha, fw->host_reg, ha->iobase,
                      sizeof (fw->host_reg) / 4, 32);
  
                  /* Disable ISP interrupts. */
!                 WRT32_IO_REG(ha, ictrl, 0);
!                 RD32_IO_REG(ha, ictrl);
!                 ADAPTER_STATE_LOCK(ha);
!                 ha->flags &= ~INTERRUPTS_ENABLED;
!                 ADAPTER_STATE_UNLOCK(ha);
  
                  /* Shadow registers. */
  
                  WRT32_IO_REG(ha, io_base_addr, 0x0F70);
                  RD32_IO_REG(ha, io_base_addr);
--- 14599,14609 ----
                  /* Host interface registers. */
                  (void) ql_read_regs(ha, fw->host_reg, ha->iobase,
                      sizeof (fw->host_reg) / 4, 32);
  
                  /* Disable ISP interrupts. */
!                 ql_disable_intr(ha);
  
                  /* Shadow registers. */
  
                  WRT32_IO_REG(ha, io_base_addr, 0x0F70);
                  RD32_IO_REG(ha, io_base_addr);
*** 13863,13878 ****
          }
  
          /* Get the request queue */
          if (rval == QL_SUCCESS) {
                  uint32_t        cnt;
!                 uint32_t        *w32 = (uint32_t *)ha->request_ring_bp;
  
                  /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                     REQUEST_Q_BUFFER_OFFSET, sizeof (fw->req_q),
!                     DDI_DMA_SYNC_FORKERNEL);
  
                  for (cnt = 0; cnt < sizeof (fw->req_q) / 4; cnt++) {
                          fw->req_q[cnt] = *w32++;
                          LITTLE_ENDIAN_32(&fw->req_q[cnt]);
                  }
--- 14896,14910 ----
          }
  
          /* Get the request queue */
          if (rval == QL_SUCCESS) {
                  uint32_t        cnt;
!                 uint32_t        *w32 = (uint32_t *)ha->req_q[0]->req_ring.bp;
  
                  /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->req_q[0]->req_ring.dma_handle,
!                     0, sizeof (fw->req_q), DDI_DMA_SYNC_FORKERNEL);
  
                  for (cnt = 0; cnt < sizeof (fw->req_q) / 4; cnt++) {
                          fw->req_q[cnt] = *w32++;
                          LITTLE_ENDIAN_32(&fw->req_q[cnt]);
                  }
*** 13879,13894 ****
          }
  
          /* Get the response queue */
          if (rval == QL_SUCCESS) {
                  uint32_t        cnt;
!                 uint32_t        *w32 = (uint32_t *)ha->response_ring_bp;
  
                  /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                     RESPONSE_Q_BUFFER_OFFSET, sizeof (fw->rsp_q),
!                     DDI_DMA_SYNC_FORKERNEL);
  
                  for (cnt = 0; cnt < sizeof (fw->rsp_q) / 4; cnt++) {
                          fw->rsp_q[cnt] = *w32++;
                          LITTLE_ENDIAN_32(&fw->rsp_q[cnt]);
                  }
--- 14911,14926 ----
          }
  
          /* Get the response queue */
          if (rval == QL_SUCCESS) {
                  uint32_t        cnt;
!                 uint32_t        *w32 =
!                     (uint32_t *)ha->rsp_queues[0]->rsp_ring.bp;
  
                  /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->rsp_queues[0]->rsp_ring.dma_handle,
!                     0, sizeof (fw->rsp_q), DDI_DMA_SYNC_FORKERNEL);
  
                  for (cnt = 0; cnt < sizeof (fw->rsp_q) / 4; cnt++) {
                          fw->rsp_q[cnt] = *w32++;
                          LITTLE_ENDIAN_32(&fw->rsp_q[cnt]);
                  }
*** 13945,13955 ****
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  
          return (rval);
  }
  
--- 14977,14987 ----
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 13967,13989 ****
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static int
  ql_25xx_binary_fw_dump(ql_adapter_state_t *ha, ql_25xx_fw_dump_t *fw)
  {
!         uint32_t        *reg32;
          void            *bp;
          clock_t         timer;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          fw->r2h_status = RD32_IO_REG(ha, risc2host);
  
          /* Pause RISC. */
          if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
                  /* Disable ISP interrupts. */
!                 WRT16_IO_REG(ha, ictrl, 0);
  
                  WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
                  for (timer = 30000;
                      (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0 &&
                      rval == QL_SUCCESS; timer--) {
--- 14999,15029 ----
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static int
  ql_25xx_binary_fw_dump(ql_adapter_state_t *ha, ql_25xx_fw_dump_t *fw)
  {
!         uint32_t        *reg32, cnt, *w32ptr, index, *dp;
          void            *bp;
          clock_t         timer;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(ha, "started\n");
  
+         fw->req_q_size[0] = ha->req_q[0]->req_ring.size;
+         if (ha->req_q[1] != NULL) {
+                 fw->req_q_size[1] = ha->req_q[1]->req_ring.size;
+         }
+         fw->rsp_q_size = ha->rsp_queues[0]->rsp_ring.size * ha->rsp_queues_cnt;
+ 
+         fw->hccr = RD32_IO_REG(ha, hccr);
          fw->r2h_status = RD32_IO_REG(ha, risc2host);
+         fw->aer_ues = ql_pci_config_get32(ha, 0x104);
  
          /* Pause RISC. */
          if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
                  /* Disable ISP interrupts. */
!                 ql_disable_intr(ha);
  
                  WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
                  for (timer = 30000;
                      (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0 &&
                      rval == QL_SUCCESS; timer--) {
*** 14006,14016 ****
                  /* HostRisc registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7000);
                  bp = ql_read_regs(ha, fw->hostrisc_reg, ha->iobase + 0xC0,
                      16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x7010);
!                 bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
  
                  /* PCIe registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7c00);
                  WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x1);
                  bp = ql_read_regs(ha, fw->pcie_reg, ha->iobase + 0xC4,
--- 15046,15056 ----
                  /* HostRisc registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7000);
                  bp = ql_read_regs(ha, fw->hostrisc_reg, ha->iobase + 0xC0,
                      16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x7010);
!                 (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
  
                  /* PCIe registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7c00);
                  WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x1);
                  bp = ql_read_regs(ha, fw->pcie_reg, ha->iobase + 0xC4,
*** 14021,14037 ****
                  /* Host interface registers. */
                  (void) ql_read_regs(ha, fw->host_reg, ha->iobase,
                      sizeof (fw->host_reg) / 4, 32);
  
                  /* Disable ISP interrupts. */
  
-                 WRT32_IO_REG(ha, ictrl, 0);
-                 RD32_IO_REG(ha, ictrl);
-                 ADAPTER_STATE_LOCK(ha);
-                 ha->flags &= ~INTERRUPTS_ENABLED;
-                 ADAPTER_STATE_UNLOCK(ha);
- 
                  /* Shadow registers. */
  
                  WRT32_IO_REG(ha, io_base_addr, 0x0F70);
                  RD32_IO_REG(ha, io_base_addr);
  
--- 15061,15072 ----
                  /* Host interface registers. */
                  (void) ql_read_regs(ha, fw->host_reg, ha->iobase,
                      sizeof (fw->host_reg) / 4, 32);
  
                  /* Disable ISP interrupts. */
+                 ql_disable_intr(ha);
  
                  /* Shadow registers. */
  
                  WRT32_IO_REG(ha, io_base_addr, 0x0F70);
                  RD32_IO_REG(ha, io_base_addr);
  
*** 14395,14451 ****
                  bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x6F00);
                  (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
          }
  
-         /* Get the request queue */
          if (rval == QL_SUCCESS) {
!                 uint32_t        cnt;
!                 uint32_t        *w32 = (uint32_t *)ha->request_ring_bp;
! 
!                 /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                     REQUEST_Q_BUFFER_OFFSET, sizeof (fw->req_q),
!                     DDI_DMA_SYNC_FORKERNEL);
! 
!                 for (cnt = 0; cnt < sizeof (fw->req_q) / 4; cnt++) {
!                         fw->req_q[cnt] = *w32++;
!                         LITTLE_ENDIAN_32(&fw->req_q[cnt]);
                  }
          }
  
!         /* Get the respons queue */
!         if (rval == QL_SUCCESS) {
!                 uint32_t        cnt;
!                 uint32_t        *w32 = (uint32_t *)ha->response_ring_bp;
! 
!                 /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                     RESPONSE_Q_BUFFER_OFFSET, sizeof (fw->rsp_q),
!                     DDI_DMA_SYNC_FORKERNEL);
! 
!                 for (cnt = 0; cnt < sizeof (fw->rsp_q) / 4; cnt++) {
!                         fw->rsp_q[cnt] = *w32++;
!                         LITTLE_ENDIAN_32(&fw->rsp_q[cnt]);
                  }
          }
  
          /* Reset RISC. */
- 
          ql_reset_chip(ha);
  
          /* Memory. */
- 
          if (rval == QL_SUCCESS) {
                  /* Code RAM. */
                  rval = ql_read_risc_ram(ha, 0x20000,
                      sizeof (fw->code_ram) / 4, fw->code_ram);
          }
          if (rval == QL_SUCCESS) {
                  /* External Memory. */
                  rval = ql_read_risc_ram(ha, 0x100000,
!                     ha->fw_ext_memory_size / 4, fw->ext_mem);
          }
  
          /* Get the FC event trace buffer */
          if (rval == QL_SUCCESS) {
                  if (CFG_IST(ha, CFG_ENABLE_FWFCETRACE) &&
--- 15430,15529 ----
                  bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x6F00);
                  (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
          }
  
          if (rval == QL_SUCCESS) {
!                 /* Get the Queue Pointers */
!                 dp = fw->req_rsp_ext_mem;
!                 for (index = 0; index < ha->rsp_queues_cnt; index++) {
!                         if (index == 0 && ha->flags & MULTI_QUEUE) {
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[0]->mbar_req_in);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[0]->mbar_req_out);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                         } else if (index == 1 && ha->flags & MULTI_QUEUE) {
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[1]->mbar_req_in);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[1]->mbar_req_out);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                         } else {
!                                 *dp++ = 0;
!                                 *dp++ = 0;
                          }
+                         if (ha->flags & MULTI_QUEUE) {
+                                 *dp = RD32_MBAR_REG(ha,
+                                     ha->rsp_queues[index]->mbar_rsp_in);
+                                 LITTLE_ENDIAN_32(dp);
+                                 dp++;
+                                 *dp = RD32_MBAR_REG(ha,
+                                     ha->rsp_queues[index]->mbar_rsp_out);
+                                 LITTLE_ENDIAN_32(dp);
+                                 dp++;
+                         } else {
+                                 *dp++ = 0;
+                                 *dp++ = 0;
                          }
+                 }
+                 /* Get the request queue */
+                 (void) ddi_dma_sync(ha->req_q[0]->req_ring.dma_handle, 0, 0,
+                     DDI_DMA_SYNC_FORCPU);
+                 w32ptr = (uint32_t *)ha->req_q[0]->req_ring.bp;
+                 for (cnt = 0; cnt < fw->req_q_size[0] / 4; cnt++) {
+                         *dp = *w32ptr++;
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                 }
+                 if (ha->req_q[1] != NULL) {
+                         (void) ddi_dma_sync(ha->req_q[1]->req_ring.dma_handle,
+                             0, 0, DDI_DMA_SYNC_FORCPU);
+                         w32ptr = (uint32_t *)ha->req_q[1]->req_ring.bp;
+                         for (cnt = 0; cnt < fw->req_q_size[1] / 4; cnt++) {
+                                 *dp = *w32ptr++;
+                                 LITTLE_ENDIAN_32(dp);
+                                 dp++;
+                         }
+                 }
  
!                 /* Get the response queues */
!                 for (index = 0; index < ha->rsp_queues_cnt; index++) {
!                         (void) ddi_dma_sync(
!                             ha->rsp_queues[index]->rsp_ring.dma_handle,
!                             0, 0, DDI_DMA_SYNC_FORCPU);
!                         w32ptr = (uint32_t *)
!                             ha->rsp_queues[index]->rsp_ring.bp;
!                         for (cnt = 0;
!                             cnt < ha->rsp_queues[index]->rsp_ring.size / 4;
!                             cnt++) {
!                                 *dp = *w32ptr++;
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
                          }
                  }
+         }
  
          /* Reset RISC. */
          ql_reset_chip(ha);
  
          /* Memory. */
          if (rval == QL_SUCCESS) {
                  /* Code RAM. */
                  rval = ql_read_risc_ram(ha, 0x20000,
                      sizeof (fw->code_ram) / 4, fw->code_ram);
          }
          if (rval == QL_SUCCESS) {
                  /* External Memory. */
                  rval = ql_read_risc_ram(ha, 0x100000,
!                     ha->fw_ext_memory_size / 4, dp);
          }
  
          /* Get the FC event trace buffer */
          if (rval == QL_SUCCESS) {
                  if (CFG_IST(ha, CFG_ENABLE_FWFCETRACE) &&
*** 14482,14492 ****
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  
          return (rval);
  }
  
--- 15560,15570 ----
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 14504,14526 ****
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static int
  ql_81xx_binary_fw_dump(ql_adapter_state_t *ha, ql_81xx_fw_dump_t *fw)
  {
!         uint32_t        *reg32;
          void            *bp;
          clock_t         timer;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          fw->r2h_status = RD32_IO_REG(ha, risc2host);
  
          /* Pause RISC. */
          if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
                  /* Disable ISP interrupts. */
!                 WRT16_IO_REG(ha, ictrl, 0);
  
                  WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
                  for (timer = 30000;
                      (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0 &&
                      rval == QL_SUCCESS; timer--) {
--- 15582,15612 ----
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  static int
  ql_81xx_binary_fw_dump(ql_adapter_state_t *ha, ql_81xx_fw_dump_t *fw)
  {
!         uint32_t        *reg32, cnt, *w32ptr, index, *dp;
          void            *bp;
          clock_t         timer;
          int             rval = QL_SUCCESS;
  
!         QL_PRINT_3(ha, "started\n");
  
+         fw->req_q_size[0] = ha->req_q[0]->req_ring.size;
+         if (ha->req_q[1] != NULL) {
+                 fw->req_q_size[1] = ha->req_q[1]->req_ring.size;
+         }
+         fw->rsp_q_size = ha->rsp_queues[0]->rsp_ring.size * ha->rsp_queues_cnt;
+ 
+         fw->hccr = RD32_IO_REG(ha, hccr);
          fw->r2h_status = RD32_IO_REG(ha, risc2host);
+         fw->aer_ues = ql_pci_config_get32(ha, 0x104);
  
          /* Pause RISC. */
          if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
                  /* Disable ISP interrupts. */
!                 ql_disable_intr(ha);
  
                  WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
                  for (timer = 30000;
                      (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0 &&
                      rval == QL_SUCCESS; timer--) {
*** 14543,14553 ****
                  /* HostRisc registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7000);
                  bp = ql_read_regs(ha, fw->hostrisc_reg, ha->iobase + 0xC0,
                      16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x7010);
!                 bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
  
                  /* PCIe registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7c00);
                  WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x1);
                  bp = ql_read_regs(ha, fw->pcie_reg, ha->iobase + 0xC4,
--- 15629,15639 ----
                  /* HostRisc registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7000);
                  bp = ql_read_regs(ha, fw->hostrisc_reg, ha->iobase + 0xC0,
                      16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x7010);
!                 (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
  
                  /* PCIe registers. */
                  WRT32_IO_REG(ha, io_base_addr, 0x7c00);
                  WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x1);
                  bp = ql_read_regs(ha, fw->pcie_reg, ha->iobase + 0xC4,
*** 14558,14574 ****
                  /* Host interface registers. */
                  (void) ql_read_regs(ha, fw->host_reg, ha->iobase,
                      sizeof (fw->host_reg) / 4, 32);
  
                  /* Disable ISP interrupts. */
  
-                 WRT32_IO_REG(ha, ictrl, 0);
-                 RD32_IO_REG(ha, ictrl);
-                 ADAPTER_STATE_LOCK(ha);
-                 ha->flags &= ~INTERRUPTS_ENABLED;
-                 ADAPTER_STATE_UNLOCK(ha);
- 
                  /* Shadow registers. */
  
                  WRT32_IO_REG(ha, io_base_addr, 0x0F70);
                  RD32_IO_REG(ha, io_base_addr);
  
--- 15644,15655 ----
                  /* Host interface registers. */
                  (void) ql_read_regs(ha, fw->host_reg, ha->iobase,
                      sizeof (fw->host_reg) / 4, 32);
  
                  /* Disable ISP interrupts. */
+                 ql_disable_intr(ha);
  
                  /* Shadow registers. */
  
                  WRT32_IO_REG(ha, io_base_addr, 0x0F70);
                  RD32_IO_REG(ha, io_base_addr);
  
*** 14938,14994 ****
                  bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x6F00);
                  (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
          }
  
-         /* Get the request queue */
          if (rval == QL_SUCCESS) {
!                 uint32_t        cnt;
!                 uint32_t        *w32 = (uint32_t *)ha->request_ring_bp;
! 
!                 /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                     REQUEST_Q_BUFFER_OFFSET, sizeof (fw->req_q),
!                     DDI_DMA_SYNC_FORKERNEL);
! 
!                 for (cnt = 0; cnt < sizeof (fw->req_q) / 4; cnt++) {
!                         fw->req_q[cnt] = *w32++;
!                         LITTLE_ENDIAN_32(&fw->req_q[cnt]);
                  }
          }
  
!         /* Get the response queue */
!         if (rval == QL_SUCCESS) {
!                 uint32_t        cnt;
!                 uint32_t        *w32 = (uint32_t *)ha->response_ring_bp;
! 
!                 /* Sync DMA buffer. */
!                 (void) ddi_dma_sync(ha->hba_buf.dma_handle,
!                     RESPONSE_Q_BUFFER_OFFSET, sizeof (fw->rsp_q),
!                     DDI_DMA_SYNC_FORKERNEL);
! 
!                 for (cnt = 0; cnt < sizeof (fw->rsp_q) / 4; cnt++) {
!                         fw->rsp_q[cnt] = *w32++;
!                         LITTLE_ENDIAN_32(&fw->rsp_q[cnt]);
                  }
          }
  
          /* Reset RISC. */
- 
          ql_reset_chip(ha);
  
          /* Memory. */
- 
          if (rval == QL_SUCCESS) {
                  /* Code RAM. */
                  rval = ql_read_risc_ram(ha, 0x20000,
                      sizeof (fw->code_ram) / 4, fw->code_ram);
          }
          if (rval == QL_SUCCESS) {
                  /* External Memory. */
                  rval = ql_read_risc_ram(ha, 0x100000,
!                     ha->fw_ext_memory_size / 4, fw->ext_mem);
          }
  
          /* Get the FC event trace buffer */
          if (rval == QL_SUCCESS) {
                  if (CFG_IST(ha, CFG_ENABLE_FWFCETRACE) &&
--- 16019,16118 ----
                  bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
                  WRT32_IO_REG(ha, io_base_addr, 0x6F00);
                  (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
          }
  
          if (rval == QL_SUCCESS) {
!                 /* Get the Queue Pointers */
!                 dp = fw->req_rsp_ext_mem;
!                 for (index = 0; index < ha->rsp_queues_cnt; index++) {
!                         if (index == 0 && ha->flags & MULTI_QUEUE) {
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[0]->mbar_req_in);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[0]->mbar_req_out);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                         } else if (index == 1 && ha->flags & MULTI_QUEUE) {
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[1]->mbar_req_in);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                                 *dp = RD32_MBAR_REG(ha,
!                                     ha->req_q[1]->mbar_req_out);
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
!                         } else {
!                                 *dp++ = 0;
!                                 *dp++ = 0;
                          }
+                         if (ha->flags & MULTI_QUEUE) {
+                                 *dp = RD32_MBAR_REG(ha,
+                                     ha->rsp_queues[index]->mbar_rsp_in);
+                                 LITTLE_ENDIAN_32(dp);
+                                 dp++;
+                                 *dp = RD32_MBAR_REG(ha,
+                                     ha->rsp_queues[index]->mbar_rsp_out);
+                                 LITTLE_ENDIAN_32(dp);
+                                 dp++;
+                         } else {
+                                 *dp++ = 0;
+                                 *dp++ = 0;
                          }
+                 }
+                 /* Get the request queue */
+                 (void) ddi_dma_sync(ha->req_q[0]->req_ring.dma_handle, 0, 0,
+                     DDI_DMA_SYNC_FORCPU);
+                 w32ptr = (uint32_t *)ha->req_q[0]->req_ring.bp;
+                 for (cnt = 0; cnt < fw->req_q_size[0] / 4; cnt++) {
+                         *dp = *w32ptr++;
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                 }
+                 if (ha->req_q[1] != NULL) {
+                         (void) ddi_dma_sync(ha->req_q[1]->req_ring.dma_handle,
+                             0, 0, DDI_DMA_SYNC_FORCPU);
+                         w32ptr = (uint32_t *)ha->req_q[1]->req_ring.bp;
+                         for (cnt = 0; cnt < fw->req_q_size[1] / 4; cnt++) {
+                                 *dp = *w32ptr++;
+                                 LITTLE_ENDIAN_32(dp);
+                                 dp++;
+                         }
+                 }
  
!                 /* Get the response queues */
!                 for (index = 0; index < ha->rsp_queues_cnt; index++) {
!                         (void) ddi_dma_sync(
!                             ha->rsp_queues[index]->rsp_ring.dma_handle,
!                             0, 0, DDI_DMA_SYNC_FORCPU);
!                         w32ptr = (uint32_t *)
!                             ha->rsp_queues[index]->rsp_ring.bp;
!                         for (cnt = 0;
!                             cnt < ha->rsp_queues[index]->rsp_ring.size / 4;
!                             cnt++) {
!                                 *dp = *w32ptr++;
!                                 LITTLE_ENDIAN_32(dp);
!                                 dp++;
                          }
                  }
+         }
  
          /* Reset RISC. */
          ql_reset_chip(ha);
  
          /* Memory. */
          if (rval == QL_SUCCESS) {
                  /* Code RAM. */
                  rval = ql_read_risc_ram(ha, 0x20000,
                      sizeof (fw->code_ram) / 4, fw->code_ram);
          }
          if (rval == QL_SUCCESS) {
                  /* External Memory. */
                  rval = ql_read_risc_ram(ha, 0x100000,
!                     ha->fw_ext_memory_size / 4, dp);
          }
  
          /* Get the FC event trace buffer */
          if (rval == QL_SUCCESS) {
                  if (CFG_IST(ha, CFG_ENABLE_FWFCETRACE) &&
*** 15025,15035 ****
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  
          return (rval);
  }
  
--- 16149,16159 ----
  
          if (rval != QL_SUCCESS) {
                  EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
          return (rval);
  }
  
*** 15063,15085 ****
  
          for (cnt = 0; cnt < len; cnt++, risc_address++) {
                  WRT16_IO_REG(ha, mailbox_in[0], MBC_READ_RAM_EXTENDED);
                  WRT16_IO_REG(ha, mailbox_in[1], LSW(risc_address));
                  WRT16_IO_REG(ha, mailbox_in[8], MSW(risc_address));
!                 if (CFG_IST(ha, CFG_CTRL_8021)) {
                          WRT32_IO_REG(ha, nx_host_int, NX_MBX_CMD);
!                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
                          WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
                  } else {
                          WRT16_IO_REG(ha, hccr, HC_SET_HOST_INT);
                  }
                  for (timer = 6000000; timer && rval == QL_SUCCESS; timer--) {
                          if (INTERRUPT_PENDING(ha)) {
                                  stat = (uint16_t)
                                      (RD16_IO_REG(ha, risc2host) & 0xff);
                                  if ((stat == 1) || (stat == 0x10)) {
!                                         if (CFG_IST(ha, CFG_CTRL_24258081)) {
                                                  buf32[cnt] = SHORT_TO_LONG(
                                                      RD16_IO_REG(ha,
                                                      mailbox_out[2]),
                                                      RD16_IO_REG(ha,
                                                      mailbox_out[3]));
--- 16187,16209 ----
  
          for (cnt = 0; cnt < len; cnt++, risc_address++) {
                  WRT16_IO_REG(ha, mailbox_in[0], MBC_READ_RAM_EXTENDED);
                  WRT16_IO_REG(ha, mailbox_in[1], LSW(risc_address));
                  WRT16_IO_REG(ha, mailbox_in[8], MSW(risc_address));
!                 if (CFG_IST(ha, CFG_CTRL_82XX)) {
                          WRT32_IO_REG(ha, nx_host_int, NX_MBX_CMD);
!                 } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                          WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
                  } else {
                          WRT16_IO_REG(ha, hccr, HC_SET_HOST_INT);
                  }
                  for (timer = 6000000; timer && rval == QL_SUCCESS; timer--) {
                          if (INTERRUPT_PENDING(ha)) {
                                  stat = (uint16_t)
                                      (RD16_IO_REG(ha, risc2host) & 0xff);
                                  if ((stat == 1) || (stat == 0x10)) {
!                                         if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                                                  buf32[cnt] = SHORT_TO_LONG(
                                                      RD16_IO_REG(ha,
                                                      mailbox_out[2]),
                                                      RD16_IO_REG(ha,
                                                      mailbox_out[3]));
*** 15092,15124 ****
                                          break;
                                  } else if ((stat == 2) || (stat == 0x11)) {
                                          rval = RD16_IO_REG(ha, mailbox_out[0]);
                                          break;
                                  }
!                                 if (CFG_IST(ha, CFG_CTRL_8021)) {
                                          ql_8021_clr_hw_intr(ha);
                                          ql_8021_clr_fw_intr(ha);
!                                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
                                          WRT32_IO_REG(ha, hccr,
                                              HC24_CLR_RISC_INT);
                                          RD32_IO_REG(ha, hccr);
                                  } else {
                                          WRT16_IO_REG(ha, hccr,
                                              HC_CLR_RISC_INT);
                                  }
                          }
                          drv_usecwait(5);
                  }
!                 if (CFG_IST(ha, CFG_CTRL_8021)) {
                          ql_8021_clr_hw_intr(ha);
                          ql_8021_clr_fw_intr(ha);
!                 } else if (CFG_IST(ha, CFG_CTRL_242581)) {
                          WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
                          RD32_IO_REG(ha, hccr);
                  } else {
-                         WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
                          WRT16_IO_REG(ha, semaphore, 0);
                  }
  
                  if (timer == 0) {
                          rval = QL_FUNCTION_TIMEOUT;
                  }
--- 16216,16251 ----
                                          break;
                                  } else if ((stat == 2) || (stat == 0x11)) {
                                          rval = RD16_IO_REG(ha, mailbox_out[0]);
                                          break;
                                  }
!                                 if (CFG_IST(ha, CFG_CTRL_82XX)) {
                                          ql_8021_clr_hw_intr(ha);
                                          ql_8021_clr_fw_intr(ha);
!                                 } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                                          WRT32_IO_REG(ha, hccr,
                                              HC24_CLR_RISC_INT);
                                          RD32_IO_REG(ha, hccr);
                                  } else {
+                                         WRT16_IO_REG(ha, semaphore, 0);
                                          WRT16_IO_REG(ha, hccr,
                                              HC_CLR_RISC_INT);
+                                         RD16_IO_REG(ha, hccr);
                                  }
                          }
                          drv_usecwait(5);
                  }
!                 if (CFG_IST(ha, CFG_CTRL_82XX)) {
                          ql_8021_clr_hw_intr(ha);
                          ql_8021_clr_fw_intr(ha);
!                 } else if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                          WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
                          RD32_IO_REG(ha, hccr);
                  } else {
                          WRT16_IO_REG(ha, semaphore, 0);
+                         WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT);
+                         RD16_IO_REG(ha, hccr);
                  }
  
                  if (timer == 0) {
                          rval = QL_FUNCTION_TIMEOUT;
                  }
*** 15185,15205 ****
          ql_config_space_t       chs;
          caddr_t                 prop = "ql-config-space";
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
                      ddi_get_instance(dip));
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
          if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, prop) ==
              1) {
!                 QL_PRINT_2(CE_CONT, "(%d): no prop exit\n", ha->instance);
                  return (DDI_SUCCESS);
          }
  
          chs.chs_command = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
          chs.chs_header_type = (uint8_t)ql_pci_config_get8(ha,
--- 16312,16332 ----
          ql_config_space_t       chs;
          caddr_t                 prop = "ql-config-space";
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "no adapter instance=%d\n",
                      ddi_get_instance(dip));
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(ha, "started\n");
  
          /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
          if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, prop) ==
              1) {
!                 QL_PRINT_2(ha, "no prop exit\n");
                  return (DDI_SUCCESS);
          }
  
          chs.chs_command = (uint16_t)ql_pci_config_get16(ha, PCI_CONF_COMM);
          chs.chs_header_type = (uint8_t)ql_pci_config_get8(ha,
*** 15235,15245 ****
                  cmn_err(CE_WARN, "!Qlogic %s(%d) can't update prop %s",
                      QL_NAME, ddi_get_instance(dip), prop);
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (DDI_SUCCESS);
  }
  
  static int
--- 16362,16372 ----
                  cmn_err(CE_WARN, "!Qlogic %s(%d) can't update prop %s",
                      QL_NAME, ddi_get_instance(dip), prop);
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (DDI_SUCCESS);
  }
  
  static int
*** 15250,15271 ****
          ql_config_space_t       *chs_p;
          caddr_t                 prop = "ql-config-space";
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(CE_CONT, "(%d): no adapter\n",
                      ddi_get_instance(dip));
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
          if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
              DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, prop,
              (uchar_t **)&chs_p, &elements) != DDI_PROP_SUCCESS) {
!                 QL_PRINT_2(CE_CONT, "(%d): no prop exit\n", ha->instance);
                  return (DDI_FAILURE);
          }
  
          ql_pci_config_put16(ha, PCI_CONF_COMM, chs_p->chs_command);
  
--- 16377,16398 ----
          ql_config_space_t       *chs_p;
          caddr_t                 prop = "ql-config-space";
  
          ha = ddi_get_soft_state(ql_state, ddi_get_instance(dip));
          if (ha == NULL) {
!                 QL_PRINT_2(NULL, "no adapter instance=%d\n",
                      ddi_get_instance(dip));
                  return (DDI_FAILURE);
          }
  
!         QL_PRINT_3(ha, "started\n");
  
          /*LINTED [Solaris DDI_DEV_T_ANY Lint warning]*/
          if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
              DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, prop,
              (uchar_t **)&chs_p, &elements) != DDI_PROP_SUCCESS) {
!                 QL_PRINT_2(ha, "no prop exit\n");
                  return (DDI_FAILURE);
          }
  
          ql_pci_config_put16(ha, PCI_CONF_COMM, chs_p->chs_command);
  
*** 15298,15308 ****
          if (ndi_prop_remove(DDI_DEV_T_NONE, dip, prop) != DDI_PROP_SUCCESS) {
                  cmn_err(CE_WARN, "!Qlogic %s(%d): can't remove prop %s",
                      QL_NAME, ddi_get_instance(dip), prop);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (DDI_SUCCESS);
  }
  
  uint8_t
--- 16425,16435 ----
          if (ndi_prop_remove(DDI_DEV_T_NONE, dip, prop) != DDI_PROP_SUCCESS) {
                  cmn_err(CE_WARN, "!Qlogic %s(%d): can't remove prop %s",
                      QL_NAME, ddi_get_instance(dip), prop);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (DDI_SUCCESS);
  }
  
  uint8_t
*** 15409,15425 ****
   *      Kernel context.
   */
  static void
  ql_halt(ql_adapter_state_t *ha, int pwr)
  {
!         uint32_t        cnt;
          ql_tgt_t        *tq;
          ql_srb_t        *sp;
          uint16_t        index;
-         ql_link_t       *link;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Wait for all commands running to finish. */
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                  for (link = ha->dev[index].first; link != NULL;
                      link = link->next) {
--- 16536,16553 ----
   *      Kernel context.
   */
  static void
  ql_halt(ql_adapter_state_t *ha, int pwr)
  {
!         ql_link_t       *link;
!         ql_response_q_t *rsp_q;
          ql_tgt_t        *tq;
          ql_srb_t        *sp;
+         uint32_t        cnt, i;
          uint16_t        index;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Wait for all commands running to finish. */
          for (index = 0; index < DEVICE_HEAD_LIST_SIZE; index++) {
                  for (link = ha->dev[index].first; link != NULL;
                      link = link->next) {
*** 15440,15470 ****
                                          ql_delay(ha, 10000);
                                  }
                          }
  
                          /* Finish any commands waiting for more status. */
!                         if (ha->status_srb != NULL) {
!                                 sp = ha->status_srb;
!                                 ha->status_srb = NULL;
                                  sp->cmd.next = NULL;
!                                 ql_done(&sp->cmd);
                          }
  
                          /* Abort commands that did not finish. */
                          if (cnt == 0) {
!                                 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS;
                                      cnt++) {
                                          if (ha->pending_cmds.first != NULL) {
                                                  ql_start_iocb(ha, NULL);
                                                  cnt = 1;
                                          }
                                          sp = ha->outstanding_cmds[cnt];
                                          if (sp != NULL &&
                                              sp->lun_queue->target_queue ==
                                              tq) {
!                                                 (void) ql_abort((opaque_t)ha,
!                                                     sp->pkt, 0);
                                          }
                                  }
                          }
                  }
          }
--- 16568,16604 ----
                                          ql_delay(ha, 10000);
                                  }
                          }
  
                          /* Finish any commands waiting for more status. */
!                         for (i = 0; i < ha->rsp_queues_cnt; i++) {
!                                 if ((rsp_q = ha->rsp_queues[i]) != NULL &&
!                                     (sp = rsp_q->status_srb) != NULL) {
!                                         rsp_q->status_srb = NULL;
                                          sp->cmd.next = NULL;
!                                         ql_done(&sp->cmd, B_FALSE);
                                  }
+                         }
  
                          /* Abort commands that did not finish. */
                          if (cnt == 0) {
!                                 for (cnt = 1; cnt < ha->osc_max_cnt;
                                      cnt++) {
                                          if (ha->pending_cmds.first != NULL) {
                                                  ql_start_iocb(ha, NULL);
                                                  cnt = 1;
                                          }
                                          sp = ha->outstanding_cmds[cnt];
                                          if (sp != NULL &&
+                                             sp != QL_ABORTED_SRB(ha) &&
                                              sp->lun_queue->target_queue ==
                                              tq) {
!                                                 (void) ql_abort_io(ha, sp);
!                                                 sp->pkt->pkt_reason =
!                                                     CS_ABORTED;
!                                                 sp->cmd.next = NULL;
!                                                 ql_done(&sp->cmd, B_FALSE);
                                          }
                                  }
                          }
                  }
          }
*** 15479,15498 ****
          ha->port_retry_timer = 0;
          ha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
          ha->watchdog_timer = 0;
          ADAPTER_STATE_UNLOCK(ha);
  
!         if (pwr == PM_LEVEL_D3) {
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags &= ~ONLINE;
                  ADAPTER_STATE_UNLOCK(ha);
  
                  /* Reset ISP chip. */
                  ql_reset_chip(ha);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_get_dma_mem
   *      Function used to allocate dma memory.
--- 16613,16636 ----
          ha->port_retry_timer = 0;
          ha->loop_down_timer = LOOP_DOWN_TIMER_OFF;
          ha->watchdog_timer = 0;
          ADAPTER_STATE_UNLOCK(ha);
  
!         if (pwr == PM_LEVEL_D3 && ha->flags & ONLINE) {
                  ADAPTER_STATE_LOCK(ha);
                  ha->flags &= ~ONLINE;
                  ADAPTER_STATE_UNLOCK(ha);
  
+                 if (CFG_IST(ha, CFG_CTRL_82XX)) {
+                         ql_8021_clr_drv_active(ha);
+                 }
+ 
                  /* Reset ISP chip. */
                  ql_reset_chip(ha);
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_get_dma_mem
   *      Function used to allocate dma memory.
*** 15512,15526 ****
  ql_get_dma_mem(ql_adapter_state_t *ha, dma_mem_t *mem, uint32_t size,
      mem_alloc_type_t allocation_type, mem_alignment_t alignment)
  {
          int     rval;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          mem->size = size;
          mem->type = allocation_type;
!         mem->cookie_count = 1;
  
          switch (alignment) {
          case QL_DMA_DATA_ALIGN:
                  mem->alignment = QL_DMA_ALIGN_8_BYTE_BOUNDARY;
                  break;
--- 16650,16664 ----
  ql_get_dma_mem(ql_adapter_state_t *ha, dma_mem_t *mem, uint32_t size,
      mem_alloc_type_t allocation_type, mem_alignment_t alignment)
  {
          int     rval;
  
!         QL_PRINT_3(ha, "started\n");
  
          mem->size = size;
          mem->type = allocation_type;
!         mem->max_cookie_count = 1;
  
          switch (alignment) {
          case QL_DMA_DATA_ALIGN:
                  mem->alignment = QL_DMA_ALIGN_8_BYTE_BOUNDARY;
                  break;
*** 15535,15550 ****
          if ((rval = ql_alloc_phys(ha, mem, KM_SLEEP)) != QL_SUCCESS) {
                  ql_free_phys(ha, mem);
                  EL(ha, "failed, alloc_phys=%xh\n", rval);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
   * ql_alloc_phys
   *      Function used to allocate memory and zero it.
   *      Memory is below 4 GB.
   *
   * Input:
--- 16673,16710 ----
          if ((rval = ql_alloc_phys(ha, mem, KM_SLEEP)) != QL_SUCCESS) {
                  ql_free_phys(ha, mem);
                  EL(ha, "failed, alloc_phys=%xh\n", rval);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
+  * ql_free_dma_resource
+  *      Function used to free dma memory.
+  *
+  * Input:
+  *      ha:             adapter state pointer.
+  *      mem:            pointer to dma memory object.
+  *      mem->dma_handle DMA memory handle.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ void
+ ql_free_dma_resource(ql_adapter_state_t *ha, dma_mem_t *mem)
+ {
+         QL_PRINT_3(ha, "started\n");
+ 
+         ql_free_phys(ha, mem);
+ 
+         QL_PRINT_3(ha, "done\n");
+ }
+ 
+ /*
   * ql_alloc_phys
   *      Function used to allocate memory and zero it.
   *      Memory is below 4 GB.
   *
   * Input:
*** 15555,15583 ****
   *      mem->type               memory allocation type.
   *      mem->size               memory size.
   *      mem->alignment          memory alignment.
   *
   * Returns:
!  *      qn local function return status code.
   *
   * Context:
   *      Kernel context.
   */
  int
  ql_alloc_phys(ql_adapter_state_t *ha, dma_mem_t *mem, int sleep)
  {
          size_t                  rlen;
!         ddi_dma_attr_t          dma_attr;
          ddi_device_acc_attr_t   acc_attr = ql_dev_acc_attr;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
-         dma_attr = CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING) ?
-             ql_64bit_io_dma_attr : ql_32bit_io_dma_attr;
- 
          dma_attr.dma_attr_align = mem->alignment; /* DMA address alignment */
!         dma_attr.dma_attr_sgllen = (int)mem->cookie_count;
  
          /*
           * Workaround for SUN XMITS buffer must end and start on 8 byte
           * boundary. Else, hardware will overrun the buffer. Simple fix is
           * to make sure buffer has enough room for overrun.
--- 16715,16740 ----
   *      mem->type               memory allocation type.
   *      mem->size               memory size.
   *      mem->alignment          memory alignment.
   *
   * Returns:
!  *      ql local function return status code.
   *
   * Context:
   *      Kernel context.
   */
  int
  ql_alloc_phys(ql_adapter_state_t *ha, dma_mem_t *mem, int sleep)
  {
          size_t                  rlen;
!         ddi_dma_attr_t          dma_attr = ha->io_dma_attr;
          ddi_device_acc_attr_t   acc_attr = ql_dev_acc_attr;
  
!         QL_PRINT_3(ha, "started\n");
  
          dma_attr.dma_attr_align = mem->alignment; /* DMA address alignment */
!         dma_attr.dma_attr_sgllen = (int)mem->max_cookie_count;
  
          /*
           * Workaround for SUN XMITS buffer must end and start on 8 byte
           * boundary. Else, hardware will overrun the buffer. Simple fix is
           * to make sure buffer has enough room for overrun.
*** 15645,15661 ****
                  return (QL_MEMORY_ALLOC_FAILED);
          }
  
          mem->flags |= DDI_DMA_RDWR;
  
          if (ql_bind_dma_buffer(ha, mem, sleep) != DDI_DMA_MAPPED) {
                  EL(ha, "failed, ddi_dma_addr_bind_handle\n");
                  ql_free_phys(ha, mem);
                  return (QL_MEMORY_ALLOC_FAILED);
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (QL_SUCCESS);
  }
  
  /*
--- 16802,16827 ----
                  return (QL_MEMORY_ALLOC_FAILED);
          }
  
          mem->flags |= DDI_DMA_RDWR;
  
+         if (qlc_fm_check_dma_handle(ha, mem->dma_handle)
+             != DDI_FM_OK) {
+                 EL(ha, "failed, ddi_dma_addr_bind_handle\n");
+                 ql_free_phys(ha, mem);
+                 qlc_fm_report_err_impact(ha,
+                     QL_FM_EREPORT_DMA_HANDLE_CHECK);
+                 return (QL_MEMORY_ALLOC_FAILED);
+         }
+ 
          if (ql_bind_dma_buffer(ha, mem, sleep) != DDI_DMA_MAPPED) {
                  EL(ha, "failed, ddi_dma_addr_bind_handle\n");
                  ql_free_phys(ha, mem);
                  return (QL_MEMORY_ALLOC_FAILED);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (QL_SUCCESS);
  }
  
  /*
*** 15670,15795 ****
   *      Kernel context.
   */
  void
  ql_free_phys(ql_adapter_state_t *ha, dma_mem_t *mem)
  {
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (mem != NULL && mem->dma_handle != NULL) {
                  ql_unbind_dma_buffer(ha, mem);
                  switch (mem->type) {
                  case KERNEL_MEM:
                          if (mem->bp != NULL) {
                                  kmem_free(mem->bp, mem->size);
                          }
                          break;
                  case LITTLE_ENDIAN_DMA:
                  case BIG_ENDIAN_DMA:
                  case NO_SWAP_DMA:
                          if (mem->acc_handle != NULL) {
                                  ddi_dma_mem_free(&mem->acc_handle);
                                  mem->acc_handle = NULL;
                          }
                          break;
                  default:
                          break;
                  }
!                 mem->bp = NULL;
                  ddi_dma_free_handle(&mem->dma_handle);
                  mem->dma_handle = NULL;
          }
- 
-         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
- }
- 
- /*
-  * ql_alloc_dma_resouce.
-  *      Allocates DMA resource for buffer.
-  *
-  * Input:
-  *      ha:                     adapter state pointer.
-  *      mem:                    pointer to dma memory object.
-  *      sleep:                  KM_SLEEP/KM_NOSLEEP flag.
-  *      mem->cookie_count       number of segments allowed.
-  *      mem->type               memory allocation type.
-  *      mem->size               memory size.
-  *      mem->bp                 pointer to memory or struct buf
-  *
-  * Returns:
-  *      qn local function return status code.
-  *
-  * Context:
-  *      Kernel context.
-  */
- int
- ql_alloc_dma_resouce(ql_adapter_state_t *ha, dma_mem_t *mem, int sleep)
- {
-         ddi_dma_attr_t  dma_attr;
- 
-         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
- 
-         dma_attr = CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING) ?
-             ql_64bit_io_dma_attr : ql_32bit_io_dma_attr;
-         dma_attr.dma_attr_sgllen = (int)mem->cookie_count;
- 
-         /*
-          * Allocate DMA handle for command.
-          */
-         if (ddi_dma_alloc_handle(ha->dip, &dma_attr, (sleep == KM_SLEEP) ?
-             DDI_DMA_SLEEP : DDI_DMA_DONTWAIT, NULL, &mem->dma_handle) !=
-             DDI_SUCCESS) {
-                 EL(ha, "failed, ddi_dma_alloc_handle\n");
-                 mem->dma_handle = NULL;
-                 return (QL_MEMORY_ALLOC_FAILED);
          }
  
!         mem->flags = DDI_DMA_RDWR | DDI_DMA_CONSISTENT;
! 
!         if (ql_bind_dma_buffer(ha, mem, sleep) != DDI_DMA_MAPPED) {
!                 EL(ha, "failed, bind_dma_buffer\n");
!                 ddi_dma_free_handle(&mem->dma_handle);
!                 mem->dma_handle = NULL;
!                 return (QL_MEMORY_ALLOC_FAILED);
!         }
! 
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
! 
!         return (QL_SUCCESS);
  }
  
  /*
-  * ql_free_dma_resource
-  *      Frees DMA resources.
-  *
-  * Input:
-  *      ha:             adapter state pointer.
-  *      mem:            pointer to dma memory object.
-  *      mem->dma_handle DMA memory handle.
-  *
-  * Context:
-  *      Kernel context.
-  */
- void
- ql_free_dma_resource(ql_adapter_state_t *ha, dma_mem_t *mem)
- {
-         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
- 
-         ql_free_phys(ha, mem);
- 
-         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
- }
- 
- /*
   * ql_bind_dma_buffer
   *      Binds DMA buffer.
   *
   * Input:
   *      ha:                     adapter state pointer.
   *      mem:                    pointer to dma memory object.
!  *      sleep:                  KM_SLEEP or KM_NOSLEEP.
   *      mem->dma_handle         DMA memory handle.
!  *      mem->cookie_count       number of segments allowed.
   *      mem->type               memory allocation type.
   *      mem->size               memory size.
   *      mem->bp                 pointer to memory or struct buf
   *
   * Returns:
--- 16836,16890 ----
   *      Kernel context.
   */
  void
  ql_free_phys(ql_adapter_state_t *ha, dma_mem_t *mem)
  {
!         QL_PRINT_3(ha, "started\n");
  
!         if (mem != NULL) {
!                 if (mem->memflags == DDI_DMA_MAPPED) {
                          ql_unbind_dma_buffer(ha, mem);
+                 }
+ 
                  switch (mem->type) {
                  case KERNEL_MEM:
                          if (mem->bp != NULL) {
                                  kmem_free(mem->bp, mem->size);
+                                 mem->bp = NULL;
                          }
                          break;
                  case LITTLE_ENDIAN_DMA:
                  case BIG_ENDIAN_DMA:
                  case NO_SWAP_DMA:
                          if (mem->acc_handle != NULL) {
                                  ddi_dma_mem_free(&mem->acc_handle);
                                  mem->acc_handle = NULL;
+                                 mem->bp = NULL;
                          }
                          break;
                  default:
                          break;
                  }
!                 if (mem->dma_handle != NULL) {
                          ddi_dma_free_handle(&mem->dma_handle);
                          mem->dma_handle = NULL;
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_bind_dma_buffer
   *      Binds DMA buffer.
   *
   * Input:
   *      ha:                     adapter state pointer.
   *      mem:                    pointer to dma memory object.
!  *      kmflags:                KM_SLEEP or KM_NOSLEEP.
   *      mem->dma_handle         DMA memory handle.
!  *      mem->max_cookie_count   number of segments allowed.
   *      mem->type               memory allocation type.
   *      mem->size               memory size.
   *      mem->bp                 pointer to memory or struct buf
   *
   * Returns:
*** 15802,15841 ****
   *
   * Context:
   *      Kernel context.
   */
  static int
! ql_bind_dma_buffer(ql_adapter_state_t *ha, dma_mem_t *mem, int sleep)
  {
-         int                     rval;
          ddi_dma_cookie_t        *cookiep;
!         uint32_t                cnt = mem->cookie_count;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         if (mem->type == STRUCT_BUF_MEMORY) {
!                 rval = ddi_dma_buf_bind_handle(mem->dma_handle, mem->bp,
!                     mem->flags, (sleep == KM_SLEEP) ? DDI_DMA_SLEEP :
!                     DDI_DMA_DONTWAIT, NULL, &mem->cookie, &mem->cookie_count);
!         } else {
!                 rval = ddi_dma_addr_bind_handle(mem->dma_handle, NULL, mem->bp,
!                     mem->size, mem->flags, (sleep == KM_SLEEP) ?
                      DDI_DMA_SLEEP : DDI_DMA_DONTWAIT, NULL, &mem->cookie,
                      &mem->cookie_count);
-         }
  
!         if (rval == DDI_DMA_MAPPED) {
!                 if (mem->cookie_count > cnt) {
                          (void) ddi_dma_unbind_handle(mem->dma_handle);
                          EL(ha, "failed, cookie_count %d > %d\n",
!                             mem->cookie_count, cnt);
!                         rval = DDI_DMA_TOOBIG;
                  } else {
                          if (mem->cookie_count > 1) {
                                  if (mem->cookies = kmem_zalloc(
                                      sizeof (ddi_dma_cookie_t) *
!                                     mem->cookie_count, sleep)) {
                                          *mem->cookies = mem->cookie;
                                          cookiep = mem->cookies;
                                          for (cnt = 1; cnt < mem->cookie_count;
                                              cnt++) {
                                                  ddi_dma_nextcookie(
--- 16897,16929 ----
   *
   * Context:
   *      Kernel context.
   */
  static int
! ql_bind_dma_buffer(ql_adapter_state_t *ha, dma_mem_t *mem, int kmflags)
  {
          ddi_dma_cookie_t        *cookiep;
!         uint32_t                cnt;
  
!         QL_PRINT_3(ha, "started\n");
  
!         mem->memflags = ddi_dma_addr_bind_handle(mem->dma_handle, NULL,
!             mem->bp, mem->size, mem->flags, (kmflags == KM_SLEEP) ?
              DDI_DMA_SLEEP : DDI_DMA_DONTWAIT, NULL, &mem->cookie,
              &mem->cookie_count);
  
!         if (mem->memflags == DDI_DMA_MAPPED) {
!                 if (mem->cookie_count > mem->max_cookie_count) {
                          (void) ddi_dma_unbind_handle(mem->dma_handle);
                          EL(ha, "failed, cookie_count %d > %d\n",
!                             mem->cookie_count, mem->max_cookie_count);
!                         mem->memflags = (uint32_t)DDI_DMA_TOOBIG;
                  } else {
                          if (mem->cookie_count > 1) {
                                  if (mem->cookies = kmem_zalloc(
                                      sizeof (ddi_dma_cookie_t) *
!                                     mem->cookie_count, kmflags)) {
                                          *mem->cookies = mem->cookie;
                                          cookiep = mem->cookies;
                                          for (cnt = 1; cnt < mem->cookie_count;
                                              cnt++) {
                                                  ddi_dma_nextcookie(
*** 15844,15854 ****
                                          }
                                  } else {
                                          (void) ddi_dma_unbind_handle(
                                              mem->dma_handle);
                                          EL(ha, "failed, kmem_zalloc\n");
!                                         rval = DDI_DMA_NORESOURCES;
                                  }
                          } else {
                                  /*
                                   * It has been reported that dmac_size at times
                                   * may be incorrect on sparc machines so for
--- 16932,16943 ----
                                          }
                                  } else {
                                          (void) ddi_dma_unbind_handle(
                                              mem->dma_handle);
                                          EL(ha, "failed, kmem_zalloc\n");
!                                         mem->memflags = (uint32_t)
!                                             DDI_DMA_NORESOURCES;
                                  }
                          } else {
                                  /*
                                   * It has been reported that dmac_size at times
                                   * may be incorrect on sparc machines so for
*** 15859,15876 ****
                                  mem->cookies->dmac_size = mem->size;
                          }
                  }
          }
  
!         if (rval != DDI_DMA_MAPPED) {
!                 EL(ha, "failed=%xh\n", rval);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
          }
  
!         return (rval);
  }
  
  /*
   * ql_unbind_dma_buffer
   *      Unbinds DMA buffer.
--- 16948,16965 ----
                                  mem->cookies->dmac_size = mem->size;
                          }
                  }
          }
  
!         if (mem->memflags != DDI_DMA_MAPPED) {
!                 EL(ha, "failed=%xh\n", mem->memflags);
          } else {
                  /*EMPTY*/
!                 QL_PRINT_3(ha, "done\n");
          }
  
!         return (mem->memflags);
  }
  
  /*
   * ql_unbind_dma_buffer
   *      Unbinds DMA buffer.
*** 15887,15917 ****
   */
  /* ARGSUSED */
  static void
  ql_unbind_dma_buffer(ql_adapter_state_t *ha, dma_mem_t *mem)
  {
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          (void) ddi_dma_unbind_handle(mem->dma_handle);
          if (mem->cookie_count > 1) {
                  kmem_free(mem->cookies, sizeof (ddi_dma_cookie_t) *
                      mem->cookie_count);
                  mem->cookies = NULL;
          }
          mem->cookie_count = 0;
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  static int
  ql_suspend_adapter(ql_adapter_state_t *ha)
  {
!         clock_t timer = 32 * drv_usectohz(1000000);
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /*
           * First we will claim mbox ownership so that no
           * thread using mbox hangs when we disable the
           * interrupt in the middle of it.
           */
          MBX_REGISTER_LOCK(ha);
--- 16976,17018 ----
   */
  /* ARGSUSED */
  static void
  ql_unbind_dma_buffer(ql_adapter_state_t *ha, dma_mem_t *mem)
  {
!         QL_PRINT_3(ha, "started\n");
  
+         if (mem->dma_handle != NULL && mem->memflags == DDI_DMA_MAPPED) {
                  (void) ddi_dma_unbind_handle(mem->dma_handle);
+         }
          if (mem->cookie_count > 1) {
                  kmem_free(mem->cookies, sizeof (ddi_dma_cookie_t) *
                      mem->cookie_count);
                  mem->cookies = NULL;
          }
          mem->cookie_count = 0;
+         mem->memflags = (uint32_t)DDI_DMA_NORESOURCES;
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  static int
  ql_suspend_adapter(ql_adapter_state_t *ha)
  {
!         clock_t timer = (clock_t)(32 * drv_usectohz(1000000));
  
!         QL_PRINT_3(ha, "started\n");
  
+         (void) ql_wait_outstanding(ha);
+ 
          /*
+          * here we are sure that there will not be any mbox interrupt.
+          * So, let's make sure that we return back all the outstanding
+          * cmds as well as internally queued commands.
+          */
+         ql_halt(ha, PM_LEVEL_D0);
+ 
+         /*
           * First we will claim mbox ownership so that no
           * thread using mbox hangs when we disable the
           * interrupt in the middle of it.
           */
          MBX_REGISTER_LOCK(ha);
*** 15934,15961 ****
  
          /* Set busy flag. */
          ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_BUSY_FLG);
          MBX_REGISTER_UNLOCK(ha);
  
-         (void) ql_wait_outstanding(ha);
- 
-         /*
-          * here we are sure that there will not be any mbox interrupt.
-          * So, let's make sure that we return back all the outstanding
-          * cmds as well as internally queued commands.
-          */
-         ql_halt(ha, PM_LEVEL_D0);
- 
          if (ha->power_level != PM_LEVEL_D3) {
                  /* Disable ISP interrupts. */
!                 WRT16_IO_REG(ha, ictrl, 0);
          }
  
-         ADAPTER_STATE_LOCK(ha);
-         ha->flags &= ~INTERRUPTS_ENABLED;
-         ADAPTER_STATE_UNLOCK(ha);
- 
          MBX_REGISTER_LOCK(ha);
          /* Reset busy status. */
          ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & ~MBX_BUSY_FLG);
  
          /* If thread is waiting for mailbox go signal it to start. */
--- 17035,17049 ----
  
          /* Set busy flag. */
          ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_BUSY_FLG);
          MBX_REGISTER_UNLOCK(ha);
  
          if (ha->power_level != PM_LEVEL_D3) {
                  /* Disable ISP interrupts. */
!                 ql_disable_intr(ha);
          }
  
          MBX_REGISTER_LOCK(ha);
          /* Reset busy status. */
          ha->mailbox_flags = (uint8_t)(ha->mailbox_flags & ~MBX_BUSY_FLG);
  
          /* If thread is waiting for mailbox go signal it to start. */
*** 15965,15975 ****
                  cv_broadcast(&ha->cv_mbx_wait);
          }
          /* Release mailbox register lock. */
          MBX_REGISTER_UNLOCK(ha);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (QL_SUCCESS);
  }
  
  /*
--- 17053,17063 ----
                  cv_broadcast(&ha->cv_mbx_wait);
          }
          /* Release mailbox register lock. */
          MBX_REGISTER_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  
          return (QL_SUCCESS);
  }
  
  /*
*** 15985,15994 ****
--- 17073,17086 ----
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
  ql_add_link_b(ql_head_t *head, ql_link_t *link)
  {
+         if (link->head != NULL) {
+                 EL(NULL, "link in use by list=%ph\n", link->head);
+         }
+ 
          /* at the end there isn't a next */
          link->next = NULL;
  
          if ((link->prev = head->last) == NULL) {
                  head->first = link;
*** 16013,16022 ****
--- 17105,17117 ----
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
  ql_add_link_t(ql_head_t *head, ql_link_t *link)
  {
+         if (link->head != NULL) {
+                 EL(NULL, "link in use by list=%ph\n", link->head);
+         }
          link->prev = NULL;
  
          if ((link->next = head->first) == NULL) {
                  head->last = link;
          } else {
*** 16032,16049 ****
   *      Remove a link from the chain.
   *
   * Input:
   *      head = Head of link list.
   *      link = link to be removed.
!  *      LOCK must be already obtained.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
  ql_remove_link(ql_head_t *head, ql_link_t *link)
  {
          if (link->prev != NULL) {
                  if ((link->prev->next = link->next) == NULL) {
                          head->last = link->prev;
                  } else {
                          link->next->prev = link->prev;
--- 17127,17145 ----
   *      Remove a link from the chain.
   *
   * Input:
   *      head = Head of link list.
   *      link = link to be removed.
!  *      associated proper LOCK must be already obtained.
   *
   * Context:
   *      Interrupt or Kernel context, no mailbox commands allowed.
   */
  void
  ql_remove_link(ql_head_t *head, ql_link_t *link)
  {
+         if (head != NULL) {
                  if (link->prev != NULL) {
                          if ((link->prev->next = link->next) == NULL) {
                                  head->last = link->prev;
                          } else {
                                  link->next->prev = link->prev;
*** 16055,16064 ****
--- 17151,17161 ----
                  }
  
                  /* not on a queue any more */
                  link->prev = link->next = NULL;
                  link->head = NULL;
+         }
  }
  
  /*
   * ql_chg_endian
   *      Change endianess of byte array.
*** 16143,16153 ****
   *      Kernel or Interrupt context, no mailbox commands allowed.
   */
  void
  ql_delay(ql_adapter_state_t *ha, clock_t usecs)
  {
!         if (QL_DAEMON_SUSPENDED(ha) || ddi_in_panic()) {
                  drv_usecwait(usecs);
          } else {
                  delay(drv_usectohz(usecs));
          }
  }
--- 17240,17251 ----
   *      Kernel or Interrupt context, no mailbox commands allowed.
   */
  void
  ql_delay(ql_adapter_state_t *ha, clock_t usecs)
  {
!         if (ha->flags & ADAPTER_SUSPENDED || ddi_in_panic() ||
!             curthread->t_flag & T_INTR_THREAD) {
                  drv_usecwait(usecs);
          } else {
                  delay(drv_usectohz(usecs));
          }
  }
*** 16169,16199 ****
   */
  int
  ql_stall_driver(ql_adapter_state_t *ha, uint32_t options)
  {
          ql_link_t               *link;
!         ql_adapter_state_t      *ha2;
          uint32_t                timer;
  
!         QL_PRINT_3(CE_CONT, "started\n");
  
!         /* Wait for 30 seconds for daemons unstall. */
!         timer = 3000;
          link = ha == NULL ? ql_hba.first : &ha->hba;
!         while (link != NULL && timer) {
                  ha2 = link->base_address;
  
                  ql_awaken_task_daemon(ha2, NULL, DRIVER_STALL, 0);
  
                  if ((ha2->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) == 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STOP_FLG) != 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STALLED_FLG &&
!                     ql_wait_outstanding(ha2) == MAX_OUTSTANDING_COMMANDS)) {
                          link = ha == NULL ? link->next : NULL;
                          continue;
                  }
  
                  ql_delay(ha2, 10000);
                  timer--;
                  link = ha == NULL ? ql_hba.first : &ha->hba;
          }
  
--- 17267,17309 ----
   */
  int
  ql_stall_driver(ql_adapter_state_t *ha, uint32_t options)
  {
          ql_link_t               *link;
!         ql_adapter_state_t      *ha2 = NULL;
          uint32_t                timer;
  
!         QL_PRINT_3(ha, "started\n");
  
!         /* Tell all daemons to stall. */
          link = ha == NULL ? ql_hba.first : &ha->hba;
!         while (link != NULL) {
                  ha2 = link->base_address;
  
                  ql_awaken_task_daemon(ha2, NULL, DRIVER_STALL, 0);
  
+                 link = ha == NULL ? link->next : NULL;
+         }
+ 
+         /* Wait for 30 seconds for daemons stall. */
+         timer = 3000;
+         link = ha == NULL ? ql_hba.first : &ha->hba;
+         while (link != NULL && timer) {
+                 ha2 = link->base_address;
+ 
                  if ((ha2->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) == 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STOP_FLG) != 0 ||
+                     (ha2->task_daemon_flags & FIRMWARE_UP) == 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STALLED_FLG &&
!                     ql_wait_outstanding(ha2) == ha2->pha->osc_max_cnt)) {
                          link = ha == NULL ? link->next : NULL;
                          continue;
                  }
  
+                 QL_PRINT_2(ha2, "status, dtf=%xh, stf=%xh\n",
+                     ha2->task_daemon_flags, ha2->flags);
+ 
                  ql_delay(ha2, 10000);
                  timer--;
                  link = ha == NULL ? ql_hba.first : &ha->hba;
          }
  
*** 16205,16215 ****
                          ql_awaken_task_daemon(ha2, NULL, 0, DRIVER_STALL);
                  }
                  return (QL_FUNCTION_TIMEOUT);
          }
  
!         QL_PRINT_3(CE_CONT, "done\n");
  
          return (QL_SUCCESS);
  }
  
  /*
--- 17315,17325 ----
                          ql_awaken_task_daemon(ha2, NULL, 0, DRIVER_STALL);
                  }
                  return (QL_FUNCTION_TIMEOUT);
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (QL_SUCCESS);
  }
  
  /*
*** 16227,16237 ****
  {
          ql_link_t               *link;
          ql_adapter_state_t      *ha2;
          uint32_t                timer;
  
!         QL_PRINT_3(CE_CONT, "started\n");
  
          /* Tell all daemons to unstall. */
          link = ha == NULL ? ql_hba.first : &ha->hba;
          while (link != NULL) {
                  ha2 = link->base_address;
--- 17337,17347 ----
  {
          ql_link_t               *link;
          ql_adapter_state_t      *ha2;
          uint32_t                timer;
  
!         QL_PRINT_3(ha, "started\n");
  
          /* Tell all daemons to unstall. */
          link = ha == NULL ? ql_hba.first : &ha->hba;
          while (link != NULL) {
                  ha2 = link->base_address;
*** 16248,16273 ****
                  ha2 = link->base_address;
  
                  if ((ha2->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) == 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STOP_FLG) != 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STALLED_FLG) == 0) {
!                         QL_PRINT_2(CE_CONT, "(%d,%d): restarted\n",
!                             ha2->instance, ha2->vp_index);
                          ql_restart_queues(ha2);
                          link = ha == NULL ? link->next : NULL;
                          continue;
                  }
  
!                 QL_PRINT_2(CE_CONT, "(%d,%d): failed, tdf=%xh\n",
!                     ha2->instance, ha2->vp_index, ha2->task_daemon_flags);
  
                  ql_delay(ha2, 10000);
                  timer--;
                  link = ha == NULL ? ql_hba.first : &ha->hba;
          }
  
!         QL_PRINT_3(CE_CONT, "done\n");
  }
  
  /*
   * ql_setup_interrupts
   *      Sets up interrupts based on the HBA's and platform's
--- 17358,17381 ----
                  ha2 = link->base_address;
  
                  if ((ha2->task_daemon_flags & TASK_DAEMON_ALIVE_FLG) == 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STOP_FLG) != 0 ||
                      (ha2->task_daemon_flags & TASK_DAEMON_STALLED_FLG) == 0) {
!                         QL_PRINT_2(ha2, "restarted\n");
                          ql_restart_queues(ha2);
                          link = ha == NULL ? link->next : NULL;
                          continue;
                  }
  
!                 QL_PRINT_2(ha2, "status, tdf=%xh\n", ha2->task_daemon_flags);
  
                  ql_delay(ha2, 10000);
                  timer--;
                  link = ha == NULL ? ql_hba.first : &ha->hba;
          }
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_setup_interrupts
   *      Sets up interrupts based on the HBA's and platform's
*** 16287,16297 ****
  {
          int32_t         rval = DDI_FAILURE;
          int32_t         i;
          int32_t         itypes = 0;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /*
           * The Solaris Advanced Interrupt Functions (aif) are only
           * supported on s10U1 or greater.
           */
--- 17395,17405 ----
  {
          int32_t         rval = DDI_FAILURE;
          int32_t         i;
          int32_t         itypes = 0;
  
!         QL_PRINT_3(ha, "started\n");
  
          /*
           * The Solaris Advanced Interrupt Functions (aif) are only
           * supported on s10U1 or greater.
           */
*** 16334,16346 ****
          }
  
          if (rval != DDI_SUCCESS) {
                  EL(ha, "failed, aif, rval=%xh\n", rval);
          } else {
!                 /*EMPTY*/
!                 QL_PRINT_3(CE_CONT, "(%d): done\n");
          }
  
          return (rval);
  }
  
  /*
--- 17442,17458 ----
          }
  
          if (rval != DDI_SUCCESS) {
                  EL(ha, "failed, aif, rval=%xh\n", rval);
          } else {
!                 /* Setup mutexes */
!                 if ((rval = ql_init_mutex(ha)) != DDI_SUCCESS) {
!                         EL(ha, "failed, mutex init ret=%xh\n", rval);
!                         ql_release_intr(ha);
                  }
+                 QL_PRINT_3(ha, "done\n");
+         }
  
          return (rval);
  }
  
  /*
*** 16357,16382 ****
   *      Kernel context.
   */
  static int
  ql_setup_msi(ql_adapter_state_t *ha)
  {
          int32_t         count = 0;
          int32_t         avail = 0;
          int32_t         actual = 0;
          int32_t         msitype = DDI_INTR_TYPE_MSI;
          int32_t         ret;
-         ql_ifunc_t      itrfun[10] = {0};
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (ql_disable_msi != 0) {
                  EL(ha, "MSI is disabled by user\n");
                  return (DDI_FAILURE);
          }
  
          /* MSI support is only suported on 24xx HBA's. */
!         if (!(CFG_IST(ha, CFG_CTRL_24258081))) {
                  EL(ha, "HBA does not support MSI\n");
                  return (DDI_FAILURE);
          }
  
          /* Get number of MSI interrupts the system supports */
--- 17469,17494 ----
   *      Kernel context.
   */
  static int
  ql_setup_msi(ql_adapter_state_t *ha)
  {
+         uint_t          i;
          int32_t         count = 0;
          int32_t         avail = 0;
          int32_t         actual = 0;
          int32_t         msitype = DDI_INTR_TYPE_MSI;
          int32_t         ret;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (ql_disable_msi != 0) {
                  EL(ha, "MSI is disabled by user\n");
                  return (DDI_FAILURE);
          }
  
          /* MSI support is only suported on 24xx HBA's. */
!         if (!CFG_IST(ha, CFG_MSI_SUPPORT)) {
                  EL(ha, "HBA does not support MSI\n");
                  return (DDI_FAILURE);
          }
  
          /* Get number of MSI interrupts the system supports */
*** 16393,16403 ****
                  return (DDI_FAILURE);
          }
  
          /* MSI requires only 1.  */
          count = 1;
-         itrfun[0].ifunc = &ql_isr_aif;
  
          /* Allocate space for interrupt handles */
          ha->hsize = ((uint32_t)(sizeof (ddi_intr_handle_t)) * count);
          ha->htable = kmem_zalloc(ha->hsize, KM_SLEEP);
  
--- 17505,17514 ----
*** 16409,16466 ****
                  EL(ha, "failed, intr_alloc ret=%xh, count = %xh, "
                      "actual=%xh\n", ret, count, actual);
                  ql_release_intr(ha);
                  return (DDI_FAILURE);
          }
- 
          ha->intr_cnt = actual;
  
          /* Get interrupt priority */
!         if ((ret = ddi_intr_get_pri(ha->htable[0], &ha->intr_pri)) !=
!             DDI_SUCCESS) {
                  EL(ha, "failed, get_pri ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
  
          /* Add the interrupt handler */
!         if ((ret = ddi_intr_add_handler(ha->htable[0], itrfun[0].ifunc,
              (caddr_t)ha, (caddr_t)0)) != DDI_SUCCESS) {
                  EL(ha, "failed, intr_add ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
  
-         /* Setup mutexes */
-         if ((ret = ql_init_mutex(ha)) != DDI_SUCCESS) {
-                 EL(ha, "failed, mutex init ret=%xh\n", ret);
-                 ql_release_intr(ha);
-                 return (ret);
-         }
- 
          /* Get the capabilities */
          (void) ddi_intr_get_cap(ha->htable[0], &ha->intr_cap);
  
          /* Enable interrupts */
          if (ha->intr_cap & DDI_INTR_FLAG_BLOCK) {
                  if ((ret = ddi_intr_block_enable(ha->htable, ha->intr_cnt)) !=
                      DDI_SUCCESS) {
                          EL(ha, "failed, block enable, ret=%xh\n", ret);
-                         ql_destroy_mutex(ha);
                          ql_release_intr(ha);
                          return (ret);
                  }
          } else {
!                 if ((ret = ddi_intr_enable(ha->htable[0])) != DDI_SUCCESS) {
                          EL(ha, "failed, intr enable, ret=%xh\n", ret);
-                         ql_destroy_mutex(ha);
                          ql_release_intr(ha);
                          return (ret);
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (DDI_SUCCESS);
  }
  
  /*
--- 17520,17570 ----
                  EL(ha, "failed, intr_alloc ret=%xh, count = %xh, "
                      "actual=%xh\n", ret, count, actual);
                  ql_release_intr(ha);
                  return (DDI_FAILURE);
          }
          ha->intr_cnt = actual;
  
          /* Get interrupt priority */
!         if ((ret = ddi_intr_get_pri(ha->htable[0], &i)) != DDI_SUCCESS) {
                  EL(ha, "failed, get_pri ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
+         ha->intr_pri = DDI_INTR_PRI(i);
  
          /* Add the interrupt handler */
!         if ((ret = ddi_intr_add_handler(ha->htable[0], ql_isr_aif,
              (caddr_t)ha, (caddr_t)0)) != DDI_SUCCESS) {
                  EL(ha, "failed, intr_add ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
  
          /* Get the capabilities */
          (void) ddi_intr_get_cap(ha->htable[0], &ha->intr_cap);
  
          /* Enable interrupts */
          if (ha->intr_cap & DDI_INTR_FLAG_BLOCK) {
                  if ((ret = ddi_intr_block_enable(ha->htable, ha->intr_cnt)) !=
                      DDI_SUCCESS) {
                          EL(ha, "failed, block enable, ret=%xh\n", ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
          } else {
!                 for (i = 0; i < actual; i++) {
!                         if ((ret = ddi_intr_enable(ha->htable[i])) !=
!                             DDI_SUCCESS) {
                                  EL(ha, "failed, intr enable, ret=%xh\n", ret);
                                  ql_release_intr(ha);
                                  return (ret);
                          }
                  }
+         }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (DDI_SUCCESS);
  }
  
  /*
*** 16477,16590 ****
   *      Kernel context.
   */
  static int
  ql_setup_msix(ql_adapter_state_t *ha)
  {
!         uint16_t        hwvect;
          int32_t         count = 0;
          int32_t         avail = 0;
          int32_t         actual = 0;
          int32_t         msitype = DDI_INTR_TYPE_MSIX;
          int32_t         ret;
!         uint32_t        i;
!         ql_ifunc_t      itrfun[QL_MSIX_MAXAIF] = {0};
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (ql_disable_msix != 0) {
                  EL(ha, "MSI-X is disabled by user\n");
                  return (DDI_FAILURE);
          }
  
          /*
           * MSI-X support is only available on 24xx HBA's that have
           * rev A2 parts (revid = 3) or greater.
           */
!         if (!((ha->device_id == 0x2532) || (ha->device_id == 0x2432) ||
!             (ha->device_id == 0x8432) || (ha->device_id == 0x8001) ||
!             (ha->device_id == 0x8021))) {
                  EL(ha, "HBA does not support MSI-X\n");
                  return (DDI_FAILURE);
          }
  
-         if (CFG_IST(ha, CFG_CTRL_2422) && (ha->rev_id < 3)) {
-                 EL(ha, "HBA does not support MSI-X (revid)\n");
-                 return (DDI_FAILURE);
-         }
- 
          /* Per HP, these HP branded HBA's are not supported with MSI-X */
          if (ha->ven_id == 0x103C && (ha->subsys_id == 0x7041 ||
              ha->subsys_id == 0x7040 || ha->subsys_id == 0x1705)) {
                  EL(ha, "HBA does not support MSI-X (subdevid)\n");
                  return (DDI_FAILURE);
          }
  
-         /* Get the number of 24xx/25xx MSI-X h/w vectors */
-         hwvect = (uint16_t)(((CFG_IST(ha, CFG_CTRL_2422) ?
-             ql_pci_config_get16(ha, 0x7e) :
-             ql_pci_config_get16(ha, 0xa2)) & 0x3ff) + 1);
- 
-         EL(ha, "pcie config space hwvect = %d\n", hwvect);
- 
-         if (hwvect < QL_MSIX_MAXAIF) {
-                 EL(ha, "failed, min h/w vectors req'd: %d, avail: %d\n",
-                     QL_MSIX_MAXAIF, hwvect);
-                 return (DDI_FAILURE);
-         }
- 
          /* Get number of MSI-X interrupts the platform h/w supports */
!         if (((ret = ddi_intr_get_nintrs(ha->dip, msitype, &count)) !=
!             DDI_SUCCESS) || count == 0) {
!                 EL(ha, "failed, nintrs ret=%xh, cnt=%xh\n", ret, count);
                  return (DDI_FAILURE);
          }
  
          /* Get number of available system interrupts */
          if (((ret = ddi_intr_get_navail(ha->dip, msitype, &avail)) !=
              DDI_SUCCESS) || avail == 0) {
                  EL(ha, "failed, navail ret=%xh, avail=%xh\n", ret, avail);
                  return (DDI_FAILURE);
          }
  
          /* Fill out the intr table */
!         count = QL_MSIX_MAXAIF;
!         itrfun[QL_MSIX_AIF].ifunc = &ql_isr_aif;
!         itrfun[QL_MSIX_RSPQ].ifunc = &ql_isr_aif;
  
          /* Allocate space for interrupt handles */
          ha->hsize = ((uint32_t)(sizeof (ddi_intr_handle_t)) * hwvect);
!         if ((ha->htable = kmem_zalloc(ha->hsize, KM_SLEEP)) == NULL) {
!                 ha->hsize = 0;
!                 EL(ha, "failed, unable to allocate htable space\n");
!                 return (DDI_FAILURE);
!         }
  
          ha->iflags |= IFLG_INTR_MSIX;
  
          /* Allocate the interrupts */
          if (((ret = ddi_intr_alloc(ha->dip, ha->htable, msitype,
              DDI_INTR_ALLOC_NORMAL, count, &actual, 0)) != DDI_SUCCESS) ||
!             actual < QL_MSIX_MAXAIF) {
                  EL(ha, "failed, intr_alloc ret=%xh, count = %xh, "
                      "actual=%xh\n", ret, count, actual);
                  ql_release_intr(ha);
                  return (DDI_FAILURE);
          }
- 
          ha->intr_cnt = actual;
  
          /* Get interrupt priority */
!         if ((ret = ddi_intr_get_pri(ha->htable[0], &ha->intr_pri)) !=
!             DDI_SUCCESS) {
                  EL(ha, "failed, get_pri ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
  
          /* Add the interrupt handlers */
          for (i = 0; i < actual; i++) {
!                 if ((ret = ddi_intr_add_handler(ha->htable[i], itrfun[i].ifunc,
                      (void *)ha, (void *)((ulong_t)i))) != DDI_SUCCESS) {
                          EL(ha, "failed, addh#=%xh, act=%xh, ret=%xh\n", i,
                              actual, ret);
                          ql_release_intr(ha);
                          return (ret);
--- 17581,17686 ----
   *      Kernel context.
   */
  static int
  ql_setup_msix(ql_adapter_state_t *ha)
  {
!         int             hwvect;
          int32_t         count = 0;
          int32_t         avail = 0;
          int32_t         actual = 0;
          int32_t         msitype = DDI_INTR_TYPE_MSIX;
          int32_t         ret;
!         uint_t          i;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (ql_disable_msix != 0) {
                  EL(ha, "MSI-X is disabled by user\n");
                  return (DDI_FAILURE);
          }
  
+ #ifdef __x86
+         if (get_hwenv() == HW_VMWARE) {
+                 EL(ha, "running under hypervisor, disabling MSI-X\n");
+                 return (DDI_FAILURE);
+         }
+ #endif
+ 
          /*
           * MSI-X support is only available on 24xx HBA's that have
           * rev A2 parts (revid = 3) or greater.
           */
!         if (CFG_IST(ha, CFG_ISP_FW_TYPE_1) ||
!             (CFG_IST(ha, CFG_CTRL_24XX) && ha->rev_id < 3)) {
                  EL(ha, "HBA does not support MSI-X\n");
                  return (DDI_FAILURE);
          }
  
          /* Per HP, these HP branded HBA's are not supported with MSI-X */
          if (ha->ven_id == 0x103C && (ha->subsys_id == 0x7041 ||
              ha->subsys_id == 0x7040 || ha->subsys_id == 0x1705)) {
                  EL(ha, "HBA does not support MSI-X (subdevid)\n");
                  return (DDI_FAILURE);
          }
  
          /* Get number of MSI-X interrupts the platform h/w supports */
!         if (((ret = ddi_intr_get_nintrs(ha->dip, msitype, &hwvect)) !=
!             DDI_SUCCESS) || hwvect == 0) {
!                 EL(ha, "failed, nintrs ret=%xh, cnt=%xh\n", ret, hwvect);
                  return (DDI_FAILURE);
          }
+         QL_PRINT_10(ha, "ddi_intr_get_nintrs, hwvect=%d\n", hwvect);
  
          /* Get number of available system interrupts */
          if (((ret = ddi_intr_get_navail(ha->dip, msitype, &avail)) !=
              DDI_SUCCESS) || avail == 0) {
                  EL(ha, "failed, navail ret=%xh, avail=%xh\n", ret, avail);
                  return (DDI_FAILURE);
          }
+         QL_PRINT_10(ha, "ddi_intr_get_navail, avail=%d\n", avail);
  
          /* Fill out the intr table */
!         count = ha->interrupt_count;
!         if (ha->flags & MULTI_QUEUE && count < ha->mq_msix_vectors) {
!                 count = ha->mq_msix_vectors;
!                 /* don't exceed the h/w capability */
!                 if (count > hwvect) {
!                         count = hwvect;
!                 }
!         }
  
          /* Allocate space for interrupt handles */
          ha->hsize = ((uint32_t)(sizeof (ddi_intr_handle_t)) * hwvect);
!         ha->htable = kmem_zalloc(ha->hsize, KM_SLEEP);
  
          ha->iflags |= IFLG_INTR_MSIX;
  
          /* Allocate the interrupts */
          if (((ret = ddi_intr_alloc(ha->dip, ha->htable, msitype,
              DDI_INTR_ALLOC_NORMAL, count, &actual, 0)) != DDI_SUCCESS) ||
!             actual < ha->interrupt_count) {
                  EL(ha, "failed, intr_alloc ret=%xh, count = %xh, "
                      "actual=%xh\n", ret, count, actual);
                  ql_release_intr(ha);
                  return (DDI_FAILURE);
          }
          ha->intr_cnt = actual;
+         EL(ha, "min=%d, multi-q=%d, req=%d, rcv=%d\n",
+             ha->interrupt_count, ha->mq_msix_vectors, count,
+             ha->intr_cnt);
  
          /* Get interrupt priority */
!         if ((ret = ddi_intr_get_pri(ha->htable[0], &i)) != DDI_SUCCESS) {
                  EL(ha, "failed, get_pri ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
+         ha->intr_pri = DDI_INTR_PRI(i);
  
          /* Add the interrupt handlers */
          for (i = 0; i < actual; i++) {
!                 if ((ret = ddi_intr_add_handler(ha->htable[i], ql_isr_aif,
                      (void *)ha, (void *)((ulong_t)i))) != DDI_SUCCESS) {
                          EL(ha, "failed, addh#=%xh, act=%xh, ret=%xh\n", i,
                              actual, ret);
                          ql_release_intr(ha);
                          return (ret);
*** 16602,16646 ****
                          EL(ha, "failed, intr_dup#=%xh, act=%xh, ret=%xh\n",
                              i, actual, ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
!         }
! #endif
! 
!         /* Setup mutexes */
!         if ((ret = ql_init_mutex(ha)) != DDI_SUCCESS) {
!                 EL(ha, "failed, mutex init ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
  
          /* Get the capabilities */
          (void) ddi_intr_get_cap(ha->htable[0], &ha->intr_cap);
  
          /* Enable interrupts */
          if (ha->intr_cap & DDI_INTR_FLAG_BLOCK) {
!                 if ((ret = ddi_intr_block_enable(ha->htable, ha->intr_cnt)) !=
                      DDI_SUCCESS) {
                          EL(ha, "failed, block enable, ret=%xh\n", ret);
-                         ql_destroy_mutex(ha);
                          ql_release_intr(ha);
                          return (ret);
                  }
          } else {
!                 for (i = 0; i < ha->intr_cnt; i++) {
                          if ((ret = ddi_intr_enable(ha->htable[i])) !=
                              DDI_SUCCESS) {
                                  EL(ha, "failed, intr enable, ret=%xh\n", ret);
-                                 ql_destroy_mutex(ha);
                                  ql_release_intr(ha);
                                  return (ret);
                          }
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (DDI_SUCCESS);
  }
  
  /*
--- 17698,17740 ----
                          EL(ha, "failed, intr_dup#=%xh, act=%xh, ret=%xh\n",
                              i, actual, ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
!                 if ((ret = ddi_intr_enable(ha->htable[i])) != DDI_SUCCESS) {
!                         EL(ha, "failed, intr enable, ret=%xh\n", ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
+         }
+ #endif
  
          /* Get the capabilities */
          (void) ddi_intr_get_cap(ha->htable[0], &ha->intr_cap);
  
          /* Enable interrupts */
          if (ha->intr_cap & DDI_INTR_FLAG_BLOCK) {
!                 if ((ret = ddi_intr_block_enable(ha->htable, actual)) !=
                      DDI_SUCCESS) {
                          EL(ha, "failed, block enable, ret=%xh\n", ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
+                 QL_PRINT_10(ha, "intr_block_enable %d\n", actual);
          } else {
!                 for (i = 0; i < actual; i++) {
                          if ((ret = ddi_intr_enable(ha->htable[i])) !=
                              DDI_SUCCESS) {
                                  EL(ha, "failed, intr enable, ret=%xh\n", ret);
                                  ql_release_intr(ha);
                                  return (ret);
                          }
+                         QL_PRINT_10(ha, "intr_enable %d\n", i);
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (DDI_SUCCESS);
  }
  
  /*
*** 16660,16789 ****
  ql_setup_fixed(ql_adapter_state_t *ha)
  {
          int32_t         count = 0;
          int32_t         actual = 0;
          int32_t         ret;
!         uint32_t        i;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          /* Get number of fixed interrupts the system supports */
          if (((ret = ddi_intr_get_nintrs(ha->dip, DDI_INTR_TYPE_FIXED,
              &count)) != DDI_SUCCESS) || count == 0) {
                  EL(ha, "failed, nintrs ret=%xh, cnt=%xh\n", ret, count);
                  return (DDI_FAILURE);
          }
  
-         ha->iflags |= IFLG_INTR_FIXED;
- 
          /* Allocate space for interrupt handles */
          ha->hsize = ((uint32_t)(sizeof (ddi_intr_handle_t)) * count);
          ha->htable = kmem_zalloc(ha->hsize, KM_SLEEP);
  
          /* Allocate the interrupts */
          if (((ret = ddi_intr_alloc(ha->dip, ha->htable, DDI_INTR_TYPE_FIXED,
              0, count, &actual, DDI_INTR_ALLOC_STRICT)) != DDI_SUCCESS) ||
              actual < count) {
                  EL(ha, "failed, intr_alloc ret=%xh, count=%xh, "
                      "actual=%xh\n", ret, count, actual);
                  ql_release_intr(ha);
                  return (DDI_FAILURE);
          }
- 
          ha->intr_cnt = actual;
  
          /* Get interrupt priority */
!         if ((ret = ddi_intr_get_pri(ha->htable[0], &ha->intr_pri)) !=
!             DDI_SUCCESS) {
                  EL(ha, "failed, get_pri ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
  
          /* Add the interrupt handlers */
!         for (i = 0; i < ha->intr_cnt; i++) {
!                 if ((ret = ddi_intr_add_handler(ha->htable[i], &ql_isr_aif,
                      (void *)ha, (void *)((ulong_t)(i)))) != DDI_SUCCESS) {
                          EL(ha, "failed, intr_add ret=%xh\n", ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
          }
  
-         /* Setup mutexes */
-         if ((ret = ql_init_mutex(ha)) != DDI_SUCCESS) {
-                 EL(ha, "failed, mutex init ret=%xh\n", ret);
-                 ql_release_intr(ha);
-                 return (ret);
-         }
- 
          /* Enable interrupts */
!         for (i = 0; i < ha->intr_cnt; i++) {
                  if ((ret = ddi_intr_enable(ha->htable[i])) != DDI_SUCCESS) {
                          EL(ha, "failed, intr enable, ret=%xh\n", ret);
-                         ql_destroy_mutex(ha);
                          ql_release_intr(ha);
                          return (ret);
                  }
          }
  
          EL(ha, "using FIXED interupts\n");
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (DDI_SUCCESS);
  }
  
  /*
-  * ql_disable_intr
-  *      Disables interrupts
-  *
-  * Input:
-  *      ha = adapter state pointer.
-  *
-  * Returns:
-  *
-  * Context:
-  *      Kernel context.
-  */
- static void
- ql_disable_intr(ql_adapter_state_t *ha)
- {
-         uint32_t        i, rval;
- 
-         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
- 
-         if (!(ha->iflags & IFLG_INTR_AIF)) {
- 
-                 /* Disable legacy interrupts */
-                 (void) ddi_remove_intr(ha->dip, 0, ha->iblock_cookie);
- 
-         } else if ((ha->intr_cap & DDI_INTR_FLAG_BLOCK) &&
-             (ha->iflags & (IFLG_INTR_MSI | IFLG_INTR_MSIX))) {
- 
-                 /* Remove AIF block interrupts (MSI) */
-                 if ((rval = ddi_intr_block_disable(ha->htable, ha->intr_cnt))
-                     != DDI_SUCCESS) {
-                         EL(ha, "failed intr block disable, rval=%x\n", rval);
-                 }
- 
-         } else {
- 
-                 /* Remove AIF non-block interrupts (fixed).  */
-                 for (i = 0; i < ha->intr_cnt; i++) {
-                         if ((rval = ddi_intr_disable(ha->htable[i])) !=
-                             DDI_SUCCESS) {
-                                 EL(ha, "failed intr disable, intr#=%xh, "
-                                     "rval=%xh\n", i, rval);
-                         }
-                 }
-         }
- 
-         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
- }
- 
- /*
   * ql_release_intr
   *      Releases aif legacy interrupt resources
   *
   * Input:
   *      ha = adapter state pointer.
--- 17754,17831 ----
  ql_setup_fixed(ql_adapter_state_t *ha)
  {
          int32_t         count = 0;
          int32_t         actual = 0;
          int32_t         ret;
!         uint_t          i;
  
!         QL_PRINT_3(ha, "started\n");
  
+         if (ql_disable_intx != 0) {
+                 EL(ha, "INT-X is disabled by user\n");
+                 return (DDI_FAILURE);
+         }
+ 
          /* Get number of fixed interrupts the system supports */
          if (((ret = ddi_intr_get_nintrs(ha->dip, DDI_INTR_TYPE_FIXED,
              &count)) != DDI_SUCCESS) || count == 0) {
                  EL(ha, "failed, nintrs ret=%xh, cnt=%xh\n", ret, count);
                  return (DDI_FAILURE);
          }
  
          /* Allocate space for interrupt handles */
          ha->hsize = ((uint32_t)(sizeof (ddi_intr_handle_t)) * count);
          ha->htable = kmem_zalloc(ha->hsize, KM_SLEEP);
  
+         ha->iflags |= IFLG_INTR_FIXED;
+ 
          /* Allocate the interrupts */
          if (((ret = ddi_intr_alloc(ha->dip, ha->htable, DDI_INTR_TYPE_FIXED,
              0, count, &actual, DDI_INTR_ALLOC_STRICT)) != DDI_SUCCESS) ||
              actual < count) {
                  EL(ha, "failed, intr_alloc ret=%xh, count=%xh, "
                      "actual=%xh\n", ret, count, actual);
                  ql_release_intr(ha);
                  return (DDI_FAILURE);
          }
          ha->intr_cnt = actual;
  
          /* Get interrupt priority */
!         if ((ret = ddi_intr_get_pri(ha->htable[0], &i)) != DDI_SUCCESS) {
                  EL(ha, "failed, get_pri ret=%xh\n", ret);
                  ql_release_intr(ha);
                  return (ret);
          }
+         ha->intr_pri = DDI_INTR_PRI(i);
  
          /* Add the interrupt handlers */
!         for (i = 0; i < actual; i++) {
!                 if ((ret = ddi_intr_add_handler(ha->htable[i], ql_isr_aif,
                      (void *)ha, (void *)((ulong_t)(i)))) != DDI_SUCCESS) {
                          EL(ha, "failed, intr_add ret=%xh\n", ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
          }
  
          /* Enable interrupts */
!         for (i = 0; i < actual; i++) {
                  if ((ret = ddi_intr_enable(ha->htable[i])) != DDI_SUCCESS) {
                          EL(ha, "failed, intr enable, ret=%xh\n", ret);
                          ql_release_intr(ha);
                          return (ret);
                  }
          }
  
          EL(ha, "using FIXED interupts\n");
  
!         QL_PRINT_3(ha, "done\n");
  
          return (DDI_SUCCESS);
  }
  
  /*
   * ql_release_intr
   *      Releases aif legacy interrupt resources
   *
   * Input:
   *      ha = adapter state pointer.
*** 16794,16840 ****
   *      Kernel context.
   */
  static void
  ql_release_intr(ql_adapter_state_t *ha)
  {
!         int32_t         i;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (!(ha->iflags & IFLG_INTR_AIF)) {
!                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
!                 return;
!         }
! 
          ha->iflags &= ~(IFLG_INTR_AIF);
          if (ha->htable != NULL && ha->hsize > 0) {
!                 i = (int32_t)ha->hsize / (int32_t)sizeof (ddi_intr_handle_t);
                  while (i-- > 0) {
                          if (ha->htable[i] == 0) {
                                  EL(ha, "htable[%x]=0h\n", i);
                                  continue;
                          }
  
                          (void) ddi_intr_disable(ha->htable[i]);
  
                          if (i < ha->intr_cnt) {
!                                 (void) ddi_intr_remove_handler(ha->htable[i]);
                          }
- 
                          (void) ddi_intr_free(ha->htable[i]);
                  }
  
                  kmem_free(ha->htable, ha->hsize);
                  ha->htable = NULL;
          }
  
!         ha->hsize = 0;
!         ha->intr_cnt = 0;
!         ha->intr_pri = 0;
!         ha->intr_cap = 0;
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_legacy_intr
   *      Sets up legacy interrupts.
--- 17836,17891 ----
   *      Kernel context.
   */
  static void
  ql_release_intr(ql_adapter_state_t *ha)
  {
!         int32_t i, x;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (!(ha->iflags & IFLG_INTR_AIF)) {
!                 ddi_remove_intr(ha->dip, 0, ha->iblock_cookie);
!         } else {
                  ha->iflags &= ~(IFLG_INTR_AIF);
                  if (ha->htable != NULL && ha->hsize > 0) {
!                         i = x = (int32_t)ha->hsize /
!                             (int32_t)sizeof (ddi_intr_handle_t);
!                         if (ha->intr_cap & DDI_INTR_FLAG_BLOCK) {
!                                 (void) ddi_intr_block_disable(ha->htable,
!                                     ha->intr_cnt);
!                         } else {
                                  while (i-- > 0) {
                                          if (ha->htable[i] == 0) {
                                                  EL(ha, "htable[%x]=0h\n", i);
                                                  continue;
                                          }
  
                                          (void) ddi_intr_disable(ha->htable[i]);
+                                 }
+                         }
  
+                         i = x;
+                         while (i-- > 0) {
                                  if (i < ha->intr_cnt) {
!                                         (void) ddi_intr_remove_handler(
!                                             ha->htable[i]);
                                  }
                                  (void) ddi_intr_free(ha->htable[i]);
                          }
  
+                         ha->intr_cnt = 0;
+                         ha->intr_cap = 0;
+ 
                          kmem_free(ha->htable, ha->hsize);
                          ha->htable = NULL;
+                         ha->hsize = 0;
                  }
+         }
  
!         ha->intr_pri = NULL;
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_legacy_intr
   *      Sets up legacy interrupts.
*** 16852,16887 ****
   *      Kernel context.
   */
  static int
  ql_legacy_intr(ql_adapter_state_t *ha)
  {
!         int     rval = DDI_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         /* Setup mutexes */
!         if (ql_init_mutex(ha) != DDI_SUCCESS) {
!                 EL(ha, "failed, mutex init\n");
!                 return (DDI_FAILURE);
          }
  
          /* Setup standard/legacy interrupt handler */
          if (ddi_add_intr(ha->dip, (uint_t)0, &ha->iblock_cookie,
              (ddi_idevice_cookie_t *)0, ql_isr, (caddr_t)ha) != DDI_SUCCESS) {
                  cmn_err(CE_WARN, "%s(%d): Failed to add legacy interrupt",
                      QL_NAME, ha->instance);
!                 ql_destroy_mutex(ha);
!                 rval = DDI_FAILURE;
          }
- 
-         if (rval == DDI_SUCCESS) {
                  ha->iflags |= IFLG_INTR_LEGACY;
                  EL(ha, "using legacy interrupts\n");
          }
- 
-         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
- 
          return (rval);
  }
  
  /*
   * ql_init_mutex
--- 17903,17940 ----
   *      Kernel context.
   */
  static int
  ql_legacy_intr(ql_adapter_state_t *ha)
  {
!         int     rval;
  
!         QL_PRINT_3(ha, "started\n");
  
!         /* Get iblock cookies to initialize mutexes */
!         if ((rval = ddi_get_iblock_cookie(ha->dip, 0, &ha->iblock_cookie)) !=
!             DDI_SUCCESS) {
!                 EL(ha, "failed, get_iblock: %xh\n", rval);
!                 return (rval);
          }
+         ha->intr_pri = (void *)ha->iblock_cookie;
  
          /* Setup standard/legacy interrupt handler */
          if (ddi_add_intr(ha->dip, (uint_t)0, &ha->iblock_cookie,
              (ddi_idevice_cookie_t *)0, ql_isr, (caddr_t)ha) != DDI_SUCCESS) {
                  cmn_err(CE_WARN, "%s(%d): Failed to add legacy interrupt",
                      QL_NAME, ha->instance);
!                 return (rval);
          }
          ha->iflags |= IFLG_INTR_LEGACY;
+ 
+         /* Setup mutexes */
+         if ((rval = ql_init_mutex(ha)) != DDI_SUCCESS) {
+                 EL(ha, "failed, mutex init ret=%xh\n", rval);
+                 ql_release_intr(ha);
+         } else {
                  EL(ha, "using legacy interrupts\n");
          }
          return (rval);
  }
  
  /*
   * ql_init_mutex
*** 16897,16964 ****
   *      Kernel context.
   */
  static int
  ql_init_mutex(ql_adapter_state_t *ha)
  {
!         int     ret;
!         void    *intr;
  
-         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
- 
-         if (ha->iflags & IFLG_INTR_AIF) {
-                 intr = (void *)(uintptr_t)ha->intr_pri;
-         } else {
-                 /* Get iblock cookies to initialize mutexes */
-                 if ((ret = ddi_get_iblock_cookie(ha->dip, 0,
-                     &ha->iblock_cookie)) != DDI_SUCCESS) {
-                         EL(ha, "failed, get_iblock: %xh\n", ret);
-                         return (DDI_FAILURE);
-                 }
-                 intr = (void *)ha->iblock_cookie;
-         }
- 
          /* mutexes to protect the adapter state structure. */
!         mutex_init(&ha->mutex, NULL, MUTEX_DRIVER, intr);
  
!         /* mutex to protect the ISP response ring. */
!         mutex_init(&ha->intr_mutex, NULL, MUTEX_DRIVER, intr);
  
          /* mutex to protect the mailbox registers. */
!         mutex_init(&ha->mbx_mutex, NULL, MUTEX_DRIVER, intr);
  
-         /* power management protection */
-         mutex_init(&ha->pm_mutex, NULL, MUTEX_DRIVER, intr);
- 
          /* Mailbox wait and interrupt conditional variable. */
          cv_init(&ha->cv_mbx_wait, NULL, CV_DRIVER, NULL);
          cv_init(&ha->cv_mbx_intr, NULL, CV_DRIVER, NULL);
  
!         /* mutex to protect the ISP request ring. */
!         mutex_init(&ha->req_ring_mutex, NULL, MUTEX_DRIVER, intr);
  
          /* Unsolicited buffer conditional variable. */
          cv_init(&ha->cv_ub, NULL, CV_DRIVER, NULL);
  
!         mutex_init(&ha->ub_mutex, NULL, MUTEX_DRIVER, intr);
!         mutex_init(&ha->cache_mutex, NULL, MUTEX_DRIVER, intr);
  
          /* Suspended conditional variable. */
          cv_init(&ha->cv_dr_suspended, NULL, CV_DRIVER, NULL);
  
-         /* mutex to protect task daemon context. */
-         mutex_init(&ha->task_daemon_mutex, NULL, MUTEX_DRIVER, intr);
- 
-         /* Task_daemon thread conditional variable. */
-         cv_init(&ha->cv_task_daemon, NULL, CV_DRIVER, NULL);
- 
-         /* mutex to protect diag port manage interface */
-         mutex_init(&ha->portmutex, NULL, MUTEX_DRIVER, intr);
- 
          /* mutex to protect per instance f/w dump flags and buffer */
!         mutex_init(&ha->dump_mutex, NULL, MUTEX_DRIVER, intr);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (DDI_SUCCESS);
  }
  
  /*
--- 17950,17996 ----
   *      Kernel context.
   */
  static int
  ql_init_mutex(ql_adapter_state_t *ha)
  {
!         QL_PRINT_3(ha, "started\n");
  
          /* mutexes to protect the adapter state structure. */
!         mutex_init(&ha->mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
  
!         /* mutex to protect the ISP request ring. */
!         mutex_init(&ha->req_ring_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
  
+         /* I/O completion queue protection. */
+         mutex_init(&ha->comp_q_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
+         cv_init(&ha->cv_comp_thread, NULL, CV_DRIVER, NULL);
+ 
          /* mutex to protect the mailbox registers. */
!         mutex_init(&ha->mbx_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
  
          /* Mailbox wait and interrupt conditional variable. */
          cv_init(&ha->cv_mbx_wait, NULL, CV_DRIVER, NULL);
          cv_init(&ha->cv_mbx_intr, NULL, CV_DRIVER, NULL);
  
!         /* power management protection */
!         mutex_init(&ha->pm_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
  
          /* Unsolicited buffer conditional variable. */
+         mutex_init(&ha->ub_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
          cv_init(&ha->cv_ub, NULL, CV_DRIVER, NULL);
  
!         /* mutex to protect task daemon context. */
!         mutex_init(&ha->task_daemon_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
!         cv_init(&ha->cv_task_daemon, NULL, CV_DRIVER, NULL);
  
          /* Suspended conditional variable. */
          cv_init(&ha->cv_dr_suspended, NULL, CV_DRIVER, NULL);
  
          /* mutex to protect per instance f/w dump flags and buffer */
!         mutex_init(&ha->dump_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
  
!         QL_PRINT_3(ha, "done\n");
  
          return (DDI_SUCCESS);
  }
  
  /*
*** 16974,17002 ****
   *      Kernel context.
   */
  static void
  ql_destroy_mutex(ql_adapter_state_t *ha)
  {
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          mutex_destroy(&ha->dump_mutex);
!         mutex_destroy(&ha->portmutex);
          cv_destroy(&ha->cv_task_daemon);
          mutex_destroy(&ha->task_daemon_mutex);
-         cv_destroy(&ha->cv_dr_suspended);
-         mutex_destroy(&ha->cache_mutex);
-         mutex_destroy(&ha->ub_mutex);
          cv_destroy(&ha->cv_ub);
!         mutex_destroy(&ha->req_ring_mutex);
          cv_destroy(&ha->cv_mbx_intr);
          cv_destroy(&ha->cv_mbx_wait);
-         mutex_destroy(&ha->pm_mutex);
          mutex_destroy(&ha->mbx_mutex);
!         mutex_destroy(&ha->intr_mutex);
          mutex_destroy(&ha->mutex);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
   * ql_fwmodule_resolve
   *      Loads and resolves external firmware module and symbols
--- 18006,18033 ----
   *      Kernel context.
   */
  static void
  ql_destroy_mutex(ql_adapter_state_t *ha)
  {
!         QL_PRINT_3(ha, "started\n");
  
          mutex_destroy(&ha->dump_mutex);
!         cv_destroy(&ha->cv_dr_suspended);
          cv_destroy(&ha->cv_task_daemon);
          mutex_destroy(&ha->task_daemon_mutex);
          cv_destroy(&ha->cv_ub);
!         mutex_destroy(&ha->ub_mutex);
!         mutex_destroy(&ha->pm_mutex);
          cv_destroy(&ha->cv_mbx_intr);
          cv_destroy(&ha->cv_mbx_wait);
          mutex_destroy(&ha->mbx_mutex);
!         cv_destroy(&ha->cv_comp_thread);
!         mutex_destroy(&ha->comp_q_mutex);
!         mutex_destroy(&ha->req_ring_mutex);
          mutex_destroy(&ha->mutex);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
   * ql_fwmodule_resolve
   *      Loads and resolves external firmware module and symbols
*** 17022,17040 ****
  ql_fwmodule_resolve(ql_adapter_state_t *ha)
  {
          int8_t                  module[128];
          int8_t                  fw_version[128];
          uint32_t                rval = QL_SUCCESS;
!         caddr_t                 code, code02;
          uint8_t                 *p_ucfw;
          uint16_t                *p_usaddr, *p_uslen;
          uint32_t                *p_uiaddr, *p_uilen, *p_uifw;
!         uint32_t                *p_uiaddr02, *p_uilen02;
          struct fw_table         *fwt;
          extern struct fw_table  fw_table[];
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (ha->fw_module != NULL) {
                  EL(ha, "%x f/w module %d.%02d.%02d is already loaded\n",
                      ha->fw_class, ha->fw_major_version, ha->fw_minor_version,
                      ha->fw_subminor_version);
--- 18053,18071 ----
  ql_fwmodule_resolve(ql_adapter_state_t *ha)
  {
          int8_t                  module[128];
          int8_t                  fw_version[128];
          uint32_t                rval = QL_SUCCESS;
!         caddr_t                 code, code02, code03;
          uint8_t                 *p_ucfw;
          uint16_t                *p_usaddr, *p_uslen;
          uint32_t                *p_uiaddr, *p_uilen, *p_uifw;
!         uint32_t                *p_uiaddr02, *p_uilen02, *p_uilen03;
          struct fw_table         *fwt;
          extern struct fw_table  fw_table[];
  
!         QL_PRINT_3(ha, "started\n");
  
          if (ha->fw_module != NULL) {
                  EL(ha, "%x f/w module %d.%02d.%02d is already loaded\n",
                      ha->fw_class, ha->fw_major_version, ha->fw_minor_version,
                      ha->fw_subminor_version);
*** 17103,17113 ****
--- 18134,18146 ----
                  }
                  break;
  
          case 0x2400:
          case 0x2500:
+         case 0x2700:
          case 0x8100:
+         case 0x8301fc:
  
                  if ((code = ddi_modsym(ha->fw_module, "risc_code01",
                      NULL)) == NULL) {
                          rval = QL_FWSYM_NOT_FOUND;
                          EL(ha, "failed, f/w module %d rc01 symbol\n", module);
*** 17138,17147 ****
--- 18171,18198 ----
                          rval = QL_FWSYM_NOT_FOUND;
                          EL(ha, "failed, f/w module %d rcl02 symbol\n", module);
                  }
  
                  if (rval == QL_SUCCESS) {
+                         if (ha->fw_class == 0x2700) {
+                                 if ((code03 = ddi_modsym(ha->fw_module,
+                                     "tmplt_code01", NULL)) == NULL) {
+                                         EL(ha, "failed, f/w module %d "
+                                             "tmplt_code01 symbol\n", module);
+                                 } else if ((p_uilen03 = ddi_modsym(
+                                     ha->fw_module, "tmplt_code_length01",
+                                     NULL)) == NULL) {
+                                         code03 = NULL;
+                                         EL(ha, "failed, f/w module %d "
+                                             "tmplt_code_length01 symbol\n",
+                                             module);
+                                 }
+                                 ha->risc_fw[2].code = code03;
+                                 if ((ha->risc_fw[2].code = code03) != NULL) {
+                                         ha->risc_fw[2].length = *p_uilen03;
+                                 }
+                         }
                          ha->risc_fw[0].code = code;
                          ha->risc_fw[0].addr = *p_uiaddr;
                          ha->risc_fw[0].length = *p_uilen;
                          ha->risc_fw[1].code = code02;
                          ha->risc_fw[1].addr = *p_uiaddr02;
*** 17180,17197 ****
  
                          cmn_err(CE_WARN, "%s(%d): driver / f/w version "
                              "mismatch for %x: driver-%s module-%s", QL_NAME,
                              ha->instance, ha->fw_class, fwt->fw_version,
                              fw_version);
- 
-                         ha->cfg_flags |= CFG_FW_MISMATCH;
-                 } else {
-                         ha->cfg_flags &= ~CFG_FW_MISMATCH;
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 18231,18244 ----
  
                          cmn_err(CE_WARN, "%s(%d): driver / f/w version "
                              "mismatch for %x: driver-%s module-%s", QL_NAME,
                              ha->instance, ha->fw_class, fwt->fw_version,
                              fw_version);
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 17209,17219 ****
  void
  ql_port_state(ql_adapter_state_t *ha, uint32_t state, uint32_t flags)
  {
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          TASK_DAEMON_LOCK(ha);
          for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
                  if (FC_PORT_STATE_MASK(vha->state) != state) {
                          vha->state = state != FC_STATE_OFFLINE ?
--- 18256,18266 ----
  void
  ql_port_state(ql_adapter_state_t *ha, uint32_t state, uint32_t flags)
  {
          ql_adapter_state_t      *vha;
  
!         QL_PRINT_3(ha, "started\n");
  
          TASK_DAEMON_LOCK(ha);
          for (vha = ha->pha; vha != NULL; vha = vha->vp_next) {
                  if (FC_PORT_STATE_MASK(vha->state) != state) {
                          vha->state = state != FC_STATE_OFFLINE ?
*** 17222,17308 ****
                  }
          }
          ha->pha->task_daemon_flags |= flags & LOOP_DOWN;
          TASK_DAEMON_UNLOCK(ha);
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  }
  
  /*
!  * ql_el_trace_desc_ctor - Construct an extended logging trace descriptor.
   *
   * Input:       Pointer to the adapter state structure.
-  * Returns:     Success or Failure.
   * Context:     Kernel context.
   */
! int
! ql_el_trace_desc_ctor(ql_adapter_state_t *ha)
  {
!         int     rval = DDI_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
!         ha->el_trace_desc =
!             (el_trace_desc_t *)kmem_zalloc(sizeof (el_trace_desc_t), KM_SLEEP);
  
!         if (ha->el_trace_desc == NULL) {
!                 cmn_err(CE_WARN, "%s(%d): can't construct trace descriptor",
!                     QL_NAME, ha->instance);
!                 rval = DDI_FAILURE;
!         } else {
!                 ha->el_trace_desc->next         = 0;
!                 ha->el_trace_desc->trace_buffer =
!                     (char *)kmem_zalloc(EL_TRACE_BUF_SIZE, KM_SLEEP);
! 
!                 if (ha->el_trace_desc->trace_buffer == NULL) {
!                         cmn_err(CE_WARN, "%s(%d): can't get trace buffer",
!                             QL_NAME, ha->instance);
!                         kmem_free(ha->el_trace_desc, sizeof (el_trace_desc_t));
!                         rval = DDI_FAILURE;
!                 } else {
!                         ha->el_trace_desc->trace_buffer_size =
!                             EL_TRACE_BUF_SIZE;
!                         mutex_init(&ha->el_trace_desc->mutex, NULL,
                              MUTEX_DRIVER, NULL);
-                 }
-         }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
!         return (rval);
  }
  
  /*
!  * ql_el_trace_desc_dtor - Destroy an extended logging trace descriptor.
   *
   * Input:       Pointer to the adapter state structure.
-  * Returns:     Success or Failure.
   * Context:     Kernel context.
   */
! int
! ql_el_trace_desc_dtor(ql_adapter_state_t *ha)
  {
!         int     rval = DDI_SUCCESS;
! 
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
! 
!         if (ha->el_trace_desc == NULL) {
!                 cmn_err(CE_WARN, "%s(%d): can't destroy el trace descriptor",
!                     QL_NAME, ha->instance);
!                 rval = DDI_FAILURE;
!         } else {
!                 if (ha->el_trace_desc->trace_buffer != NULL) {
!                         kmem_free(ha->el_trace_desc->trace_buffer,
!                             ha->el_trace_desc->trace_buffer_size);
                  }
!                 mutex_destroy(&ha->el_trace_desc->mutex);
!                 kmem_free(ha->el_trace_desc, sizeof (el_trace_desc_t));
          }
- 
-         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
- 
-         return (rval);
  }
  
  /*
   * els_cmd_text - Return a pointer to a string describing the command
   *
--- 18269,18332 ----
                  }
          }
          ha->pha->task_daemon_flags |= flags & LOOP_DOWN;
          TASK_DAEMON_UNLOCK(ha);
  
!         QL_PRINT_3(ha, "done\n");
  }
  
  /*
!  * ql_el_trace_alloc - Construct an extended logging trace descriptor.
   *
   * Input:       Pointer to the adapter state structure.
   * Context:     Kernel context.
   */
! void
! ql_el_trace_alloc(ql_adapter_state_t *ha)
  {
!         ql_trace_entry_t        *entry;
!         size_t                  maxsize;
  
!         ha->ql_trace_desc =
!             (ql_trace_desc_t *)kmem_zalloc(
!             sizeof (ql_trace_desc_t), KM_SLEEP);
  
!         /* ql_log_entries could be adjusted in /etc/system */
!         maxsize = ql_log_entries * sizeof (ql_trace_entry_t);
!         entry = kmem_zalloc(maxsize, KM_SLEEP);
  
!         mutex_init(&ha->ql_trace_desc->mutex, NULL,
              MUTEX_DRIVER, NULL);
  
!         ha->ql_trace_desc->trace_buffer = entry;
!         ha->ql_trace_desc->trace_buffer_size = maxsize;
!         ha->ql_trace_desc->nindex = 0;
  
!         ha->ql_trace_desc->nentries = ql_log_entries;
!         ha->ql_trace_desc->start = ha->ql_trace_desc->end = 0;
!         ha->ql_trace_desc->csize = 0;
!         ha->ql_trace_desc->count = 0;
  }
  
  /*
!  * ql_el_trace_dealloc - Destroy an extended logging trace descriptor.
   *
   * Input:       Pointer to the adapter state structure.
   * Context:     Kernel context.
   */
! void
! ql_el_trace_dealloc(ql_adapter_state_t *ha)
  {
!         if (ha->ql_trace_desc != NULL) {
!                 if (ha->ql_trace_desc->trace_buffer != NULL) {
!                         kmem_free(ha->ql_trace_desc->trace_buffer,
!                             ha->ql_trace_desc->trace_buffer_size);
                  }
!                 mutex_destroy(&ha->ql_trace_desc->mutex);
!                 kmem_free(ha->ql_trace_desc,
!                     sizeof (ql_trace_desc_t));
          }
  }
  
  /*
   * els_cmd_text - Return a pointer to a string describing the command
   *
*** 17351,17405 ****
          }
          return (entry->string);
  }
  
  /*
!  * ql_els_24xx_mbox_cmd_iocb - els request indication.
   *
!  * Input:       ha = adapter state pointer.
!  *              srb = scsi request block pointer.
!  *              arg = els passthru entry iocb pointer.
   * Returns:
   * Context:     Kernel context.
   */
  void
! ql_els_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *srb, void *arg)
  {
          els_descriptor_t        els_desc;
  
          /* Extract the ELS information */
!         ql_fca_isp_els_request(ha, (fc_packet_t *)srb->pkt, &els_desc);
  
          /* Construct the passthru entry */
          ql_isp_els_request_ctor(&els_desc, (els_passthru_entry_t *)arg);
  
          /* Ensure correct endianness */
          ql_isp_els_handle_cmd_endian(ha, srb);
  }
  
  /*
!  * ql_fca_isp_els_request - Extract into an els descriptor the info required
   *                          to build an els_passthru iocb from an fc packet.
   *
!  * Input:       ha = adapter state pointer.
!  *              pkt = fc packet pointer
!  *              els_desc = els descriptor pointer
!  * Returns:
!  * Context:     Kernel context.
   */
  static void
! ql_fca_isp_els_request(ql_adapter_state_t *ha, fc_packet_t *pkt,
!     els_descriptor_t *els_desc)
  {
          ls_code_t       els;
  
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
              (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
  
          els_desc->els = els.ls_code;
  
!         els_desc->els_handle = ha->hba_buf.acc_handle;
          els_desc->d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          els_desc->s_id.b24 = pkt->pkt_cmd_fhdr.s_id;
          /* if n_port_handle is not < 0x7d use 0 */
          if (LOCAL_LOOP_ID(ha->n_port->n_port_handle)) {
                  els_desc->n_port_handle = ha->n_port->n_port_handle;
--- 18375,18440 ----
          }
          return (entry->string);
  }
  
  /*
!  * ql_els_24xx_iocb
!  *      els request indication.
   *
!  * Input:
!  *      ha:     adapter state pointer.
!  *      req_q:  request queue structure pointer.
!  *      srb:    scsi request block pointer.
!  *      arg:    els passthru entry iocb pointer.
!  *
   * Returns:
+  *
   * Context:     Kernel context.
   */
  void
! ql_els_24xx_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *srb,
!     void *arg)
  {
          els_descriptor_t        els_desc;
  
          /* Extract the ELS information */
!         ql_fca_isp_els_request(ha, req_q, (fc_packet_t *)srb->pkt,
!             &els_desc);
  
          /* Construct the passthru entry */
          ql_isp_els_request_ctor(&els_desc, (els_passthru_entry_t *)arg);
  
          /* Ensure correct endianness */
          ql_isp_els_handle_cmd_endian(ha, srb);
  }
  
  /*
!  * ql_fca_isp_els_request
!  *      Extract into an els descriptor the info required
   *      to build an els_passthru iocb from an fc packet.
   *
!  * Input:
!  *      ha:             adapter state pointer.
!  *      req_q:          request queue structure pointer.
!  *      pkt:            fc packet pointer
!  *      els_desc:       els descriptor pointer
!  *
!  * Context:
!  *      Kernel context.
   */
  static void
! ql_fca_isp_els_request(ql_adapter_state_t *ha, ql_request_q_t *req_q,
!     fc_packet_t *pkt, els_descriptor_t *els_desc)
  {
          ls_code_t       els;
  
          ddi_rep_get8(pkt->pkt_cmd_acc, (uint8_t *)&els,
              (uint8_t *)pkt->pkt_cmd, sizeof (els), DDI_DEV_AUTOINCR);
  
          els_desc->els = els.ls_code;
  
!         els_desc->els_handle = req_q->req_ring.acc_handle;
          els_desc->d_id.b24 = pkt->pkt_cmd_fhdr.d_id;
          els_desc->s_id.b24 = pkt->pkt_cmd_fhdr.s_id;
          /* if n_port_handle is not < 0x7d use 0 */
          if (LOCAL_LOOP_ID(ha->n_port->n_port_handle)) {
                  els_desc->n_port_handle = ha->n_port->n_port_handle;
*** 17472,17482 ****
          ddi_put32(els_desc->els_handle, &els_entry->rcv_payld_data_bcnt,
              els_desc->rsp_byte_count);
          ddi_put32(els_desc->els_handle, &els_entry->xmt_payld_data_bcnt,
              els_desc->cmd_byte_count);
          /* Load transmit data segments and count. */
!         ptr32 = (uint32_t *)&els_entry->xmt_dseg_0_address;
          ddi_put16(els_desc->els_handle, &els_entry->xmt_dseg_count, 1);
          ddi_put32(els_desc->els_handle, ptr32++, els_desc->tx_dsd.addr[0]);
          ddi_put32(els_desc->els_handle, ptr32++, els_desc->tx_dsd.addr[1]);
          ddi_put32(els_desc->els_handle, ptr32++, els_desc->tx_dsd.length);
          ddi_put16(els_desc->els_handle, &els_entry->rcv_dseg_count, 1);
--- 18507,18517 ----
          ddi_put32(els_desc->els_handle, &els_entry->rcv_payld_data_bcnt,
              els_desc->rsp_byte_count);
          ddi_put32(els_desc->els_handle, &els_entry->xmt_payld_data_bcnt,
              els_desc->cmd_byte_count);
          /* Load transmit data segments and count. */
!         ptr32 = (uint32_t *)&els_entry->dseg;
          ddi_put16(els_desc->els_handle, &els_entry->xmt_dseg_count, 1);
          ddi_put32(els_desc->els_handle, ptr32++, els_desc->tx_dsd.addr[0]);
          ddi_put32(els_desc->els_handle, ptr32++, els_desc->tx_dsd.addr[1]);
          ddi_put32(els_desc->els_handle, ptr32++, els_desc->tx_dsd.length);
          ddi_put16(els_desc->els_handle, &els_entry->rcv_dseg_count, 1);
*** 17619,17629 ****
   */
  static int
  ql_n_port_plogi(ql_adapter_state_t *ha)
  {
          int             rval;
!         ql_tgt_t        *tq;
          ql_head_t done_q = { NULL, NULL };
  
          rval = QL_SUCCESS;
  
          if (ha->topology & QL_N_PORT) {
--- 18654,18664 ----
   */
  static int
  ql_n_port_plogi(ql_adapter_state_t *ha)
  {
          int             rval;
!         ql_tgt_t        *tq = NULL;
          ql_head_t done_q = { NULL, NULL };
  
          rval = QL_SUCCESS;
  
          if (ha->topology & QL_N_PORT) {
*** 17640,17650 ****
                  } else {
                          EL(ha, "n_port_handle = %x, tq = %x\n",
                              ha->n_port->n_port_handle, tq);
                  }
                  if (done_q.first != NULL) {
!                         ql_done(done_q.first);
                  }
          }
          return (rval);
  }
  
--- 18675,18685 ----
                  } else {
                          EL(ha, "n_port_handle = %x, tq = %x\n",
                              ha->n_port->n_port_handle, tq);
                  }
                  if (done_q.first != NULL) {
!                         ql_done(done_q.first, B_FALSE);
                  }
          }
          return (rval);
  }
  
*** 17658,17677 ****
   * Return Values:
   *   if first == second return  0
   *   if first > second  return  1
   *   if first < second  return -1
   */
  int
  ql_wwn_cmp(ql_adapter_state_t *ha, la_wwn_t *first, la_wwn_t *second)
  {
          la_wwn_t t1, t2;
          int rval;
  
-         EL(ha, "WWPN=%08x%08x\n",
-             BE_32(first->i_wwn[0]), BE_32(first->i_wwn[1]));
-         EL(ha, "WWPN=%08x%08x\n",
-             BE_32(second->i_wwn[0]), BE_32(second->i_wwn[1]));
          /*
           * Fibre Channel protocol is big endian, so compare
           * as big endian values
           */
          t1.i_wwn[0] = BE_32(first->i_wwn[0]);
--- 18693,18709 ----
   * Return Values:
   *   if first == second return  0
   *   if first > second  return  1
   *   if first < second  return -1
   */
+ /* ARGSUSED */
  int
  ql_wwn_cmp(ql_adapter_state_t *ha, la_wwn_t *first, la_wwn_t *second)
  {
          la_wwn_t t1, t2;
          int rval;
  
          /*
           * Fibre Channel protocol is big endian, so compare
           * as big endian values
           */
          t1.i_wwn[0] = BE_32(first->i_wwn[0]);
*** 17697,17745 ****
          }
          return (rval);
  }
  
  /*
-  * ql_wait_for_td_stop
-  *      Wait for task daemon to stop running.  Internal command timeout
-  *      is approximately 30 seconds, so it may help in some corner
-  *      cases to wait that long
-  *
-  * Input:
-  *      ha = adapter state pointer.
-  *
-  * Returns:
-  *      DDI_SUCCESS or DDI_FAILURE.
-  *
-  * Context:
-  *      Kernel context.
-  */
- 
- static int
- ql_wait_for_td_stop(ql_adapter_state_t *ha)
- {
-         int     rval = DDI_FAILURE;
-         UINT16  wait_cnt;
- 
-         for (wait_cnt = 0; wait_cnt < 3000; wait_cnt++) {
-                 /* The task daemon clears the stop flag on exit. */
-                 if (ha->task_daemon_flags & TASK_DAEMON_STOP_FLG) {
-                         if (ha->cprinfo.cc_events & CALLB_CPR_START ||
-                             ddi_in_panic()) {
-                                 drv_usecwait(10000);
-                         } else {
-                                 delay(drv_usectohz(10000));
-                         }
-                 } else {
-                         rval = DDI_SUCCESS;
-                         break;
-                 }
-         }
-         return (rval);
- }
- 
- /*
   * ql_nvram_cache_desc_ctor - Construct an nvram cache descriptor.
   *
   * Input:       Pointer to the adapter state structure.
   * Returns:     Success or Failure.
   * Context:     Kernel context.
--- 18729,18738 ----
*** 17747,17757 ****
  int
  ql_nvram_cache_desc_ctor(ql_adapter_state_t *ha)
  {
          int     rval = DDI_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          ha->nvram_cache =
              (nvram_cache_desc_t *)kmem_zalloc(sizeof (nvram_cache_desc_t),
              KM_SLEEP);
  
--- 18740,18750 ----
  int
  ql_nvram_cache_desc_ctor(ql_adapter_state_t *ha)
  {
          int     rval = DDI_SUCCESS;
  
!         QL_PRINT_3(ha, "started\n");
  
          ha->nvram_cache =
              (nvram_cache_desc_t *)kmem_zalloc(sizeof (nvram_cache_desc_t),
              KM_SLEEP);
  
*** 17758,17768 ****
          if (ha->nvram_cache == NULL) {
                  cmn_err(CE_WARN, "%s(%d): can't construct nvram cache"
                      " descriptor", QL_NAME, ha->instance);
                  rval = DDI_FAILURE;
          } else {
!                 if (CFG_IST(ha, CFG_CTRL_24258081)) {
                          ha->nvram_cache->size = sizeof (nvram_24xx_t);
                  } else {
                          ha->nvram_cache->size = sizeof (nvram_t);
                  }
                  ha->nvram_cache->cache =
--- 18751,18761 ----
          if (ha->nvram_cache == NULL) {
                  cmn_err(CE_WARN, "%s(%d): can't construct nvram cache"
                      " descriptor", QL_NAME, ha->instance);
                  rval = DDI_FAILURE;
          } else {
!                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
                          ha->nvram_cache->size = sizeof (nvram_24xx_t);
                  } else {
                          ha->nvram_cache->size = sizeof (nvram_t);
                  }
                  ha->nvram_cache->cache =
*** 17773,17789 ****
                          kmem_free(ha->nvram_cache,
                              sizeof (nvram_cache_desc_t));
                          ha->nvram_cache = 0;
                          rval = DDI_FAILURE;
                  } else {
-                         mutex_init(&ha->nvram_cache->mutex, NULL,
-                             MUTEX_DRIVER, NULL);
                          ha->nvram_cache->valid = 0;
                  }
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
--- 18766,18780 ----
                          kmem_free(ha->nvram_cache,
                              sizeof (nvram_cache_desc_t));
                          ha->nvram_cache = 0;
                          rval = DDI_FAILURE;
                  } else {
                          ha->nvram_cache->valid = 0;
                  }
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
*** 17796,17806 ****
  int
  ql_nvram_cache_desc_dtor(ql_adapter_state_t *ha)
  {
          int     rval = DDI_SUCCESS;
  
!         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
  
          if (ha->nvram_cache == NULL) {
                  cmn_err(CE_WARN, "%s(%d): can't destroy nvram descriptor",
                      QL_NAME, ha->instance);
                  rval = DDI_FAILURE;
--- 18787,18797 ----
  int
  ql_nvram_cache_desc_dtor(ql_adapter_state_t *ha)
  {
          int     rval = DDI_SUCCESS;
  
!         QL_PRINT_3(ha, "started\n");
  
          if (ha->nvram_cache == NULL) {
                  cmn_err(CE_WARN, "%s(%d): can't destroy nvram descriptor",
                      QL_NAME, ha->instance);
                  rval = DDI_FAILURE;
*** 17807,17949 ****
          } else {
                  if (ha->nvram_cache->cache != NULL) {
                          kmem_free(ha->nvram_cache->cache,
                              ha->nvram_cache->size);
                  }
-                 mutex_destroy(&ha->nvram_cache->mutex);
                  kmem_free(ha->nvram_cache, sizeof (nvram_cache_desc_t));
          }
  
!         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
  
          return (rval);
  }
  
  /*
!  * ql_process_idc_event - Handle an Inter-Driver Communication async event.
   *
   * Input:       Pointer to the adapter state structure.
!  * Returns:     void
   * Context:     Kernel context.
   */
  static void
! ql_process_idc_event(ql_adapter_state_t *ha)
  {
          int     rval;
  
!         switch (ha->idc_mb[0]) {
!         case MBA_IDC_NOTIFICATION:
                  /*
!                  * The informational opcode (idc_mb[2]) can be a
!                  * defined value or the mailbox command being executed
!                  * on another function which stimulated this IDC message.
                   */
!                 ADAPTER_STATE_LOCK(ha);
!                 switch (ha->idc_mb[2]) {
!                 case IDC_OPC_DRV_START:
!                         if (ha->idc_flash_acc != 0) {
!                                 ha->idc_flash_acc--;
!                                 if (ha->idc_flash_acc == 0) {
!                                         ha->idc_flash_acc_timer = 0;
!                                         GLOBAL_HW_UNLOCK();
                                  }
                          }
!                         if (ha->idc_restart_cnt != 0) {
!                                 ha->idc_restart_cnt--;
!                                 if (ha->idc_restart_cnt == 0) {
!                                         ha->idc_restart_timer = 0;
!                                         ADAPTER_STATE_UNLOCK(ha);
!                                         TASK_DAEMON_LOCK(ha);
!                                         ha->task_daemon_flags &= ~DRIVER_STALL;
!                                         TASK_DAEMON_UNLOCK(ha);
!                                         ql_restart_queues(ha);
!                                 } else {
!                                         ADAPTER_STATE_UNLOCK(ha);
                                  }
                          } else {
!                                 ADAPTER_STATE_UNLOCK(ha);
                          }
                          break;
-                 case IDC_OPC_FLASH_ACC:
-                         ha->idc_flash_acc_timer = 30;
-                         if (ha->idc_flash_acc == 0) {
-                                 GLOBAL_HW_LOCK();
                          }
!                         ha->idc_flash_acc++;
!                         ADAPTER_STATE_UNLOCK(ha);
                          break;
!                 case IDC_OPC_RESTART_MPI:
!                         ha->idc_restart_timer = 30;
!                         ha->idc_restart_cnt++;
                          ADAPTER_STATE_UNLOCK(ha);
                          TASK_DAEMON_LOCK(ha);
                          ha->task_daemon_flags |= DRIVER_STALL;
                          TASK_DAEMON_UNLOCK(ha);
!                         break;
!                 case IDC_OPC_PORT_RESET_MBC:
!                 case IDC_OPC_SET_PORT_CONFIG_MBC:
!                         ha->idc_restart_timer = 30;
!                         ha->idc_restart_cnt++;
!                         ADAPTER_STATE_UNLOCK(ha);
!                         TASK_DAEMON_LOCK(ha);
!                         ha->task_daemon_flags |= DRIVER_STALL;
!                         TASK_DAEMON_UNLOCK(ha);
                          (void) ql_wait_outstanding(ha);
-                         break;
-                 default:
-                         ADAPTER_STATE_UNLOCK(ha);
-                         EL(ha, "Unknown IDC opcode=%xh %xh\n", ha->idc_mb[0],
-                             ha->idc_mb[2]);
-                         break;
                  }
!                 /*
!                  * If there is a timeout value associated with this IDC
!                  * notification then there is an implied requirement
!                  * that we return an ACK.
!                  */
!                 if (ha->idc_mb[1] & IDC_TIMEOUT_MASK) {
                          rval = ql_idc_ack(ha);
                          if (rval != QL_SUCCESS) {
!                                 EL(ha, "idc_ack status=%xh %xh\n", rval,
!                                     ha->idc_mb[2]);
                          }
                  }
!                 break;
!         case MBA_IDC_COMPLETE:
!                 /*
!                  * We don't ACK completions, only these require action.
!                  */
!                 switch (ha->idc_mb[2]) {
!                 case IDC_OPC_PORT_RESET_MBC:
!                 case IDC_OPC_SET_PORT_CONFIG_MBC:
                          ADAPTER_STATE_LOCK(ha);
!                         if (ha->idc_restart_cnt != 0) {
!                                 ha->idc_restart_cnt--;
!                                 if (ha->idc_restart_cnt == 0) {
!                                         ha->idc_restart_timer = 0;
                                          ADAPTER_STATE_UNLOCK(ha);
                                          TASK_DAEMON_LOCK(ha);
                                          ha->task_daemon_flags &= ~DRIVER_STALL;
                                          TASK_DAEMON_UNLOCK(ha);
                                          ql_restart_queues(ha);
                                  } else {
!                                         ADAPTER_STATE_UNLOCK(ha);
                                  }
                          } else {
!                                 ADAPTER_STATE_UNLOCK(ha);
                          }
                          break;
-                 default:
-                         break; /* Don't care... */
                  }
                  break;
!         case MBA_IDC_TIME_EXTENDED:
!                 QL_PRINT_10(CE_CONT, "(%d): MBA_IDC_TIME_EXTENDED="
!                     "%xh\n", ha->instance, ha->idc_mb[2]);
                  break;
          default:
!                 EL(ha, "Inconsistent IDC event =%xh %xh\n", ha->idc_mb[0],
!                     ha->idc_mb[2]);
                  ADAPTER_STATE_UNLOCK(ha);
                  break;
          }
  }
--- 18798,23022 ----
          } else {
                  if (ha->nvram_cache->cache != NULL) {
                          kmem_free(ha->nvram_cache->cache,
                              ha->nvram_cache->size);
                  }
                  kmem_free(ha->nvram_cache, sizeof (nvram_cache_desc_t));
          }
  
!         QL_PRINT_3(ha, "done\n");
  
          return (rval);
  }
  
  /*
!  * ql_plogi_params_desc_ctor - Construct an plogi retry params descriptor.
   *
   * Input:       Pointer to the adapter state structure.
!  * Returns:     Success or Failure.
   * Context:     Kernel context.
   */
+ int
+ ql_plogi_params_desc_ctor(ql_adapter_state_t *ha)
+ {
+         int     rval = DDI_SUCCESS;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         ha->plogi_params =
+             (plogi_params_desc_t *)kmem_zalloc(sizeof (plogi_params_desc_t),
+             KM_SLEEP);
+ 
+         if (ha->plogi_params == NULL) {
+                 cmn_err(CE_WARN, "%s(%d): can't construct plogi params"
+                     " descriptor", QL_NAME, ha->instance);
+                 rval = DDI_FAILURE;
+         } else {
+                 /* default initializers. */
+                 ha->plogi_params->retry_cnt = QL_PLOGI_RETRY_CNT;
+                 ha->plogi_params->retry_dly_usec = QL_PLOGI_RETRY_DLY_USEC;
+         }
+ 
+         QL_PRINT_3(ha, "done\n");
+ 
+         return (rval);
+ }
+ 
+ /*
+  * ql_plogi_params_desc_dtor - Destroy an plogi retry params descriptor.
+  *
+  * Input:       Pointer to the adapter state structure.
+  * Returns:     Success or Failure.
+  * Context:     Kernel context.
+  */
+ int
+ ql_plogi_params_desc_dtor(ql_adapter_state_t *ha)
+ {
+         int     rval = DDI_SUCCESS;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         if (ha->plogi_params == NULL) {
+                 cmn_err(CE_WARN, "%s(%d): can't destroy plogi params"
+                     " descriptor", QL_NAME, ha->instance);
+                 rval = DDI_FAILURE;
+         } else {
+                 kmem_free(ha->plogi_params, sizeof (plogi_params_desc_t));
+         }
+ 
+         QL_PRINT_3(ha, "done\n");
+ 
+         return (rval);
+ }
+ 
+ /*
+  * ql_toggle_loop_state
+  *      Changes looop state to offline and then online.
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ void
+ ql_toggle_loop_state(ql_adapter_state_t *ha)
+ {
+         uint32_t        timer;
+ 
+         if (LOOP_READY(ha)) {
+                 ql_port_state(ha, FC_STATE_OFFLINE, FC_STATE_CHANGE);
+                 ql_awaken_task_daemon(ha, NULL, FC_STATE_CHANGE, 0);
+                 for (timer = 30; timer; timer--) {
+                         if (!(ha->task_daemon_flags & FC_STATE_CHANGE)) {
+                                 break;
+                         }
+                         delay(100);
+                 }
+                 ql_loop_online(ha);
+         }
+ }
+ 
+ /*
+  * ql_create_queues
+  *      Allocate request/response queues.
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *
+  * Returns:
+  *      ql driver local function return status codes
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static int
+ ql_create_queues(ql_adapter_state_t *ha)
+ {
+         int             rval;
+         uint16_t        cnt;
+ 
+         QL_PRINT_10(ha, "started\n");
+ 
+         if (ha->req_q[0] != NULL) {
+                 QL_PRINT_10(ha, "done, queues already exist\n");
+                 return (QL_SUCCESS);
+         }
+         if (ha->vp_index != 0) {
+                 QL_PRINT_10(ha, "done, no multi-req-q \n");
+                 ha->req_q[0] = ha->pha->req_q[0];
+                 ha->req_q[1] = ha->pha->req_q[1];
+                 ha->rsp_queues = ha->pha->rsp_queues;
+                 return (QL_SUCCESS);
+         }
+ 
+         /* Setup request queue buffer pointers. */
+         ha->req_q[0] = kmem_zalloc(sizeof (ql_request_q_t), KM_SLEEP);
+ 
+         /* Allocate request queue. */
+         ha->req_q[0]->req_entry_cnt = REQUEST_ENTRY_CNT;
+         ha->req_q[0]->req_ring.size = ha->req_q[0]->req_entry_cnt *
+             REQUEST_ENTRY_SIZE;
+         if (ha->flags & QUEUE_SHADOW_PTRS) {
+                 ha->req_q[0]->req_ring.size += SHADOW_ENTRY_SIZE;
+         }
+         ha->req_q[0]->req_ring.type = LITTLE_ENDIAN_DMA;
+         ha->req_q[0]->req_ring.max_cookie_count = 1;
+         ha->req_q[0]->req_ring.alignment = 64;
+         if ((rval = ql_alloc_phys(ha, &ha->req_q[0]->req_ring, KM_SLEEP)) !=
+             QL_SUCCESS) {
+                 EL(ha, "request queue status=%xh", rval);
+                 ql_delete_queues(ha);
+                 return (rval);
+         }
+         if (ha->flags & QUEUE_SHADOW_PTRS) {
+                 ha->req_q[0]->req_out_shadow_ofst =
+                     ha->req_q[0]->req_entry_cnt * REQUEST_ENTRY_SIZE;
+                 ha->req_q[0]->req_out_shadow_ptr = (uint32_t *)
+                     ((caddr_t)ha->req_q[0]->req_ring.bp +
+                     ha->req_q[0]->req_out_shadow_ofst);
+         }
+         ha->fw_transfer_size = ha->req_q[0]->req_ring.size;
+         if (ha->flags & MULTI_QUEUE) {
+                 ha->req_q[0]->mbar_req_in = MBAR2_REQ_IN;
+                 ha->req_q[0]->mbar_req_out = MBAR2_REQ_OUT;
+                 if (ha->req_q[0]->mbar_req_in >= ha->mbar_size) {
+                         EL(ha, "req_q index=0 exceeds mbar size=%xh",
+                             ha->mbar_size);
+                         ql_delete_queues(ha);
+                         return (QL_FUNCTION_PARAMETER_ERROR);
+                 }
+         }
+ 
+         /* Allocate response queues. */
+         if (ha->rsp_queues == NULL) {
+                 if (ha->intr_cnt > 1) {
+                         ha->rsp_queues_cnt = (uint8_t)(ha->intr_cnt - 1);
+                 } else {
+                         ha->rsp_queues_cnt = 1;
+                 }
+                 ha->io_min_rsp_q_number = 0;
+                 if (ha->rsp_queues_cnt > 1) {
+                         /* Setup request queue buffer pointers. */
+                         ha->req_q[1] = kmem_zalloc(sizeof (ql_request_q_t),
+                             KM_SLEEP);
+ 
+                         /* Allocate request queue. */
+                         ha->req_q[1]->req_entry_cnt = REQUEST_ENTRY_CNT;
+                         ha->req_q[1]->req_ring.size =
+                             ha->req_q[1]->req_entry_cnt * REQUEST_ENTRY_SIZE;
+                         if (ha->flags & QUEUE_SHADOW_PTRS) {
+                                 ha->req_q[1]->req_ring.size +=
+                                     SHADOW_ENTRY_SIZE;
+                         }
+                         ha->req_q[1]->req_ring.type = LITTLE_ENDIAN_DMA;
+                         ha->req_q[1]->req_ring.max_cookie_count = 1;
+                         ha->req_q[1]->req_ring.alignment = 64;
+                         if ((rval = ql_alloc_phys(ha, &ha->req_q[1]->req_ring,
+                             KM_SLEEP)) != QL_SUCCESS) {
+                                 EL(ha, "ha request queue status=%xh", rval);
+                                 ql_delete_queues(ha);
+                                 return (rval);
+                         }
+                         if (ha->flags & QUEUE_SHADOW_PTRS) {
+                                 ha->req_q[1]->req_out_shadow_ofst =
+                                     ha->req_q[1]->req_entry_cnt *
+                                     REQUEST_ENTRY_SIZE;
+                                 ha->req_q[1]->req_out_shadow_ptr = (uint32_t *)
+                                     ((caddr_t)ha->req_q[1]->req_ring.bp +
+                                     ha->req_q[1]->req_out_shadow_ofst);
+                         }
+                         ha->req_q[1]->req_q_number = 1;
+                         if (ha->flags & MULTI_QUEUE) {
+                                 ha->req_q[1]->mbar_req_in =
+                                     ha->mbar_queue_offset + MBAR2_REQ_IN;
+                                 ha->req_q[1]->mbar_req_out =
+                                     ha->mbar_queue_offset + MBAR2_REQ_OUT;
+                                 if (ha->req_q[1]->mbar_req_in >=
+                                     ha->mbar_size) {
+                                         EL(ha, "ha req_q index=1 exceeds mbar "
+                                             "size=%xh", ha->mbar_size);
+                                         ql_delete_queues(ha);
+                                         return (QL_FUNCTION_PARAMETER_ERROR);
+                                 }
+                         }
+                 }
+ 
+                 /* Allocate enough rsp_queue descriptors for IRM */
+                 ha->rsp_queues_size = (ha->hsize / sizeof (ddi_intr_handle_t)) *
+                     sizeof (ql_response_q_t *);
+                 ha->rsp_queues = kmem_zalloc(ha->rsp_queues_size, KM_SLEEP);
+ 
+                 /* Create rsp_queues for the current rsp_queue_cnt */
+                 for (cnt = 0; cnt < ha->rsp_queues_cnt; cnt++) {
+                         rval = ql_create_rsp_queue(ha, cnt);
+                         if (rval != QL_SUCCESS) {
+                                 ql_delete_queues(ha);
+                                 return (rval);
+                         }
+                 }
+         }
+ 
+         if (CFG_IST(ha, CFG_FCIP_TYPE_1)) {
+                 /* Allocate IP receive queue. */
+                 ha->rcv_ring.size = RCVBUF_QUEUE_SIZE;
+                 ha->rcv_ring.type = LITTLE_ENDIAN_DMA;
+                 ha->rcv_ring.max_cookie_count = 1;
+                 ha->rcv_ring.alignment = 64;
+                 if ((rval = ql_alloc_phys(ha, &ha->rcv_ring, KM_SLEEP)) !=
+                     QL_SUCCESS) {
+                         EL(ha, "receive queue status=%xh", rval);
+                         ql_delete_queues(ha);
+                         return (rval);
+                 }
+         }
+ 
+         QL_PRINT_10(ha, "done\n");
+ 
+         return (rval);
+ }
+ 
+ /*
+  * ql_create_rsp_queue
+  *      Allocate a response queues.
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *
+  * Returns:
+  *      ql driver local function return status codes
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static int
+ ql_create_rsp_queue(ql_adapter_state_t *ha, uint16_t rsp_q_indx)
+ {
+         ql_response_q_t *rsp_q;
+         int             rval = QL_SUCCESS;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         ha->rsp_queues[rsp_q_indx] = rsp_q =
+             kmem_zalloc(sizeof (ql_response_q_t), KM_SLEEP);
+         /* ISP response ring and interrupt protection. */
+         mutex_init(&rsp_q->intr_mutex, NULL, MUTEX_DRIVER, ha->intr_pri);
+         rsp_q->rsp_q_number = rsp_q_indx;
+         rsp_q->msi_x_vector = (uint16_t)(rsp_q_indx + 1);
+         if (ha->flags & MULTI_QUEUE) {
+                 rsp_q->mbar_rsp_in = rsp_q->rsp_q_number *
+                     ha->mbar_queue_offset + MBAR2_RESP_IN;
+                 rsp_q->mbar_rsp_out = rsp_q->rsp_q_number *
+                     ha->mbar_queue_offset + MBAR2_RESP_OUT;
+                 if (rsp_q->mbar_rsp_in >= ha->mbar_size) {
+                         EL(ha, "rsp_q index=%xh exceeds mbar size=%xh",
+                             rsp_q_indx, ha->mbar_size);
+                         return (QL_FUNCTION_PARAMETER_ERROR);
+                 }
+         }
+ 
+         rsp_q->rsp_entry_cnt = RESPONSE_ENTRY_CNT;
+         rsp_q->rsp_ring.size = rsp_q->rsp_entry_cnt * RESPONSE_ENTRY_SIZE;
+         if (ha->flags & QUEUE_SHADOW_PTRS) {
+                 rsp_q->rsp_ring.size += SHADOW_ENTRY_SIZE;
+         }
+         rsp_q->rsp_ring.type = LITTLE_ENDIAN_DMA;
+         rsp_q->rsp_ring.max_cookie_count = 1;
+         rsp_q->rsp_ring.alignment = 64;
+         rval = ql_alloc_phys(ha, &rsp_q->rsp_ring, KM_SLEEP);
+         if (rval != QL_SUCCESS) {
+                 EL(ha, "response queue status=%xh", rval);
+         }
+         if (ha->flags & QUEUE_SHADOW_PTRS) {
+                 rsp_q->rsp_in_shadow_ofst =
+                     rsp_q->rsp_entry_cnt * RESPONSE_ENTRY_SIZE;
+                 rsp_q->rsp_in_shadow_ptr = (uint32_t *)
+                     ((caddr_t)rsp_q->rsp_ring.bp +
+                     rsp_q->rsp_in_shadow_ofst);
+         }
+ 
+         QL_PRINT_3(ha, "done\n");
+         return (rval);
+ }
+ 
+ /*
+  * ql_delete_queues
+  *      Deletes request/response queues.
+  *
+  * Input:
+  *      ha = adapter state pointer.
+  *
+  * Context:
+  *      Kernel context.
+  */
  static void
! ql_delete_queues(ql_adapter_state_t *ha)
  {
+         uint32_t        cnt;
+ 
+         QL_PRINT_10(ha, "started\n");
+ 
+         if (ha->vp_index != 0) {
+                 QL_PRINT_10(ha, "done, no multi-req-q \n");
+                 ha->req_q[0] = ha->req_q[1] = NULL;
+                 return;
+         }
+         if (ha->req_q[0] != NULL) {
+                 ql_free_phys(ha, &ha->req_q[0]->req_ring);
+                 kmem_free(ha->req_q[0], sizeof (ql_request_q_t));
+                 ha->req_q[0] = NULL;
+         }
+         if (ha->req_q[1] != NULL) {
+                 ql_free_phys(ha, &ha->req_q[1]->req_ring);
+                 kmem_free(ha->req_q[1], sizeof (ql_request_q_t));
+                 ha->req_q[1] = NULL;
+         }
+ 
+         if (ha->rsp_queues != NULL) {
+                 ql_response_q_t *rsp_q;
+ 
+                 for (cnt = 0; cnt < ha->rsp_queues_cnt; cnt++) {
+                         if ((rsp_q = ha->rsp_queues[cnt]) == NULL) {
+                                 continue;
+                         }
+ 
+                         mutex_destroy(&rsp_q->intr_mutex);
+                         ql_free_phys(ha, &rsp_q->rsp_ring);
+                         kmem_free(rsp_q, sizeof (ql_response_q_t));
+                         ha->rsp_queues[cnt] = NULL;
+                 }
+                 kmem_free(ha->rsp_queues, ha->rsp_queues_size);
+                 ha->rsp_queues = NULL;
+         }
+ 
+         QL_PRINT_10(ha, "done\n");
+ }
+ 
+ /*
+  * ql_multi_queue_support
+  *      Test 2500 or 8100 adapters for support of multi-queue
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *
+  * Returns:
+  *      ql local function return status code.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static int
+ ql_multi_queue_support(ql_adapter_state_t *ha)
+ {
+         uint32_t        data;
          int             rval;
  
!         data = ql_get_cap_ofst(ha, PCI_CAP_ID_MSI_X);
!         if ((ql_pci_config_get16(ha, data + PCI_MSIX_CTRL) &
!             PCI_MSIX_TBL_SIZE_MASK) > 2) {
!                 ha->mbar_size = MBAR2_MULTI_Q_MAX * MBAR2_REG_OFFSET;
! 
!                 if (ql_map_mem_bar(ha, &ha->mbar_dev_handle, &ha->mbar,
!                     PCI_CONF_BASE3, ha->mbar_size) != DDI_SUCCESS) {
!                         return (QL_FUNCTION_FAILED);
!                 }
!                 if ((rval = qlc_fm_check_acc_handle(ha,
!                     ha->mbar_dev_handle)) != DDI_FM_OK) {
!                         qlc_fm_report_err_impact(ha,
!                             QL_FM_EREPORT_ACC_HANDLE_CHECK);
!                         EL(ha, "fm_check_acc_handle mbar_dev_handle "
!                             "status=%xh\n", rval);
!                         return (QL_FUNCTION_FAILED);
!                 }
!                 return (QL_SUCCESS);
!         }
!         return (QL_FUNCTION_FAILED);
! }
! 
! /*
!  * ql_get_cap_ofst
!  *      Locates PCI configuration space capability pointer
!  *
!  * Input:
!  *      ha:     adapter state pointer.
!  *      cap_id: Capability ID.
!  *
!  * Returns:
!  *      capability offset
!  *
!  * Context:
!  *      Kernel context.
!  */
! int
! ql_get_cap_ofst(ql_adapter_state_t *ha, uint8_t cap_id)
! {
!         int     cptr = PCI_CAP_NEXT_PTR_NULL;
! 
!         QL_PRINT_3(ha, "started\n");
! 
!         if (ql_pci_config_get16(ha, PCI_CONF_STAT) & PCI_STAT_CAP) {
!                 cptr = ql_pci_config_get8(ha, PCI_CONF_CAP_PTR);
! 
!                 while (cptr != PCI_CAP_NEXT_PTR_NULL) {
!                         if (ql_pci_config_get8(ha, cptr) == cap_id) {
!                                 break;
!                         }
!                         cptr = ql_pci_config_get8(ha, cptr + PCI_CAP_NEXT_PTR);
!                 }
!         }
! 
!         QL_PRINT_3(ha, "done\n");
!         return (cptr);
! }
! 
! /*
!  * ql_map_mem_bar
!  *      Map Mem BAR
!  *
!  * Input:
!  *      ha:              adapter state pointer.
!  *      handlep:        access handle pointer.
!  *      addrp:          address structure pointer.
!  *      ofst:           BAR offset.
!  *      len:            address space length.
!  *
!  * Returns:
!  *      DDI_SUCCESS or DDI_FAILURE.
!  *
!  * Context:
!  *      Kernel context.
!  */
! static int
! ql_map_mem_bar(ql_adapter_state_t *ha, ddi_acc_handle_t *handlep,
!     caddr_t *addrp, uint32_t ofst, uint32_t len)
! {
!         caddr_t         nreg;
!         pci_regspec_t   *reg, *reg2;
!         int             rval;
!         uint_t          rlen;
!         uint32_t        rcnt, w32, nreg_size;
! 
!         QL_PRINT_10(ha, "started\n");
! 
!         /* Check for Mem BAR */
!         w32 = ql_pci_config_get32(ha, ofst);
!         if (w32 == 0) {
!                 EL(ha, "no Mem BAR %xh\n", ofst);
!                 return (DDI_FAILURE);
!         }
! 
!         /*LINTED [Solaris DDI_DEV_T_ANY Lint error]*/
!         if ((rval = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, ha->dip,
!             DDI_PROP_DONTPASS, "reg", (int **)®, &rlen)) !=
!             DDI_PROP_SUCCESS) {
!                 EL(ha, "ddi_prop_lookup_int_array status=%xh\n", rval);
!                 return (DDI_FAILURE);
!         }
!         rlen = (uint_t)(rlen * sizeof (int));   /* in bytes */
!         rcnt = (uint32_t)(rlen / sizeof (pci_regspec_t));
! 
!         /* Check if register already added. */
!         reg2 = reg;
!         for (w32 = 0; w32 < rcnt; w32++) {
!                 if ((reg2->pci_phys_hi & PCI_REG_REG_M) == ofst) {
!                         EL(ha, "already mapped\n");
!                         break;
!                 }
!                 reg2++;
!         }
!         if (w32 == rcnt) {
                  /*
!                  * Allocate memory for the existing reg(s) plus one and then
!                  * build it.
                   */
!                 nreg_size = (uint32_t)(rlen + sizeof (pci_regspec_t));
!                 nreg = kmem_zalloc(nreg_size, KM_SLEEP);
! 
!                 /*
!                  * Find a current map memory reg to copy.
!                  */
!                 reg2 = reg;
!                 while ((reg2->pci_phys_hi & PCI_REG_ADDR_M) !=
!                     PCI_ADDR_MEM32 && (reg2->pci_phys_hi & PCI_REG_ADDR_M) !=
!                     PCI_ADDR_MEM64) {
!                         reg2++;
!                         if ((caddr_t)reg2 >= (caddr_t)reg + rlen) {
!                                 reg2 = reg;
!                                 break;
                          }
                  }
!                 w32 = (reg2->pci_phys_hi & ~PCI_REG_REG_M) | ofst;
! 
!                 bcopy(reg, nreg, rlen);
!                 reg2 = (pci_regspec_t *)(nreg + rlen);
! 
!                 reg2->pci_phys_hi = w32;
!                 reg2->pci_phys_mid = 0;
!                 reg2->pci_phys_low = 0;
!                 reg2->pci_size_hi = 0;
!                 reg2->pci_size_low = len;
! 
!                 /*
!                  * Write out the new "reg" property
!                  */
!                 /*LINTED [Solaris DDI_DEV_T_NONE Lint error]*/
!                 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, ha->dip,
!                     "reg", (int *)nreg, (uint_t)(nreg_size / sizeof (int)));
! 
!                 w32 = (uint_t)(nreg_size / sizeof (pci_regspec_t) - 1);
!                 kmem_free((caddr_t)nreg, nreg_size);
          }
+ 
+         ddi_prop_free(reg);
+ 
+         /* Map register */
+         rval = ddi_regs_map_setup(ha->dip, w32, addrp, 0, len,
+             &ql_dev_acc_attr, handlep);
+         if (rval != DDI_SUCCESS || *addrp == NULL || *handlep == NULL) {
+                 EL(ha, "regs_map status=%xh, base=%xh, handle=%xh\n",
+                     rval, *addrp, *handlep);
+                 if (*handlep != NULL) {
+                         ddi_regs_map_free(handlep);
+                         *handlep = NULL;
+                 }
+         }
+ 
+         QL_PRINT_10(ha, "done\n");
+ 
+         return (rval);
+ }
+ 
+ /*
+  * ql_intr_lock
+  *      Acquires all interrupt locks.
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *
+  * Context:
+  *      Kernel/Interrupt context.
+  */
+ void
+ ql_intr_lock(ql_adapter_state_t *ha)
+ {
+         uint16_t        cnt;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         if (ha->rsp_queues != NULL) {
+                 for (cnt = 0; cnt < ha->rsp_queues_cnt; cnt++) {
+                         if (ha->rsp_queues[cnt] != NULL) {
+                                 INDX_INTR_LOCK(ha, cnt);
+                         }
+                 }
+         }
+         QL_PRINT_3(ha, "done\n");
+ }
+ 
+ /*
+  * ql_intr_unlock
+  *      Releases all interrupt locks.
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *
+  * Context:
+  *      Kernel/Interrupt context.
+  */
+ void
+ ql_intr_unlock(ql_adapter_state_t *ha)
+ {
+         uint16_t        cnt;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         if (ha->rsp_queues != NULL) {
+                 for (cnt = 0; cnt < ha->rsp_queues_cnt; cnt++) {
+                         if (ha->rsp_queues[cnt] != NULL) {
+                                 INDX_INTR_UNLOCK(ha, cnt);
+                         }
+                 }
+         }
+         QL_PRINT_3(ha, "done\n");
+ }
+ 
+ /*
+  * ql_completion_thread
+  *      I/O completion thread.
+  *
+  * Input:
+  *      arg:    port info pointer.
+  *      COMP_Q_LOCK must be acquired prior to call.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static void
+ ql_completion_thread(void *arg)
+ {
+         ql_srb_t                *sp;
+         ql_adapter_state_t      *ha = arg;
+ 
+         QL_PRINT_3(ha, "started, hsp=%p\n", (void *)&sp);
+ 
+         COMP_Q_LOCK(ha);
+         ha->comp_thds_active++;
+         ha->comp_thds_awake++;
+         while (!(ha->flags & COMP_THD_TERMINATE)) {
+                 /* process completion queue items */
+                 while (ha->comp_q.first != NULL) {
+                         sp = (ha->comp_q.first)->base_address;
+                         /* Remove command from completion queue */
+                         ql_remove_link(&ha->comp_q, &sp->cmd);
+                         COMP_Q_UNLOCK(ha);
+                         QL_PRINT_3(ha, "pkt_comp, sp=%p, pkt_state=%xh, "
+                             "hsp=%p\n", (void*)sp, sp->pkt->pkt_state,
+                             (void *)&sp);
+                         (sp->pkt->pkt_comp)(sp->pkt);
+                         COMP_Q_LOCK(ha);
+                 }
+                 ha->comp_thds_awake--;
+                 QL_PRINT_3(ha, "sleep, hsp=%p\n", (void *)&sp);
+                 cv_wait(&ha->cv_comp_thread, &ha->comp_q_mutex);
+                 QL_PRINT_3(ha, "awoke, hsp=%p\n", (void *)&sp);
+         }
+         ha->comp_thds_awake--;
+         ha->comp_thds_active--;
+         COMP_Q_UNLOCK(ha);
+ 
+         QL_PRINT_3(ha, "done\n");
+ }
+ 
+ /*
+  * ql_io_comp
+  *      Transport I/O completion
+  *
+  * Input:
+  *      sp:     SRB structure pointer
+  *
+  * Context:
+  *      Kernel context.
+  */
+ void
+ ql_io_comp(ql_srb_t *sp)
+ {
+         ql_adapter_state_t      *ha = sp->ha->pha;
+ 
+         QL_PRINT_3(ha, "started, sp=%ph, d_id=%xh\n", (void*)sp,
+             sp->pkt->pkt_cmd_fhdr.d_id);
+ 
+         if (sp->pkt->pkt_comp && !ddi_in_panic()) {
+                 QL_PRINT_3(ha, "added to comp_q\n");
+                 COMP_Q_LOCK(ha);
+                 ql_add_link_b(&ha->comp_q, &sp->cmd);
+                 if (ha->comp_thds_awake < ha->comp_thds_active) {
+                         ha->comp_thds_awake++;
+                         QL_PRINT_3(ha, "signal\n");
+                         cv_signal(&ha->cv_comp_thread);
+                 }
+                 COMP_Q_UNLOCK(ha);
+         }
+ 
+         QL_PRINT_3(ha, "done\n");
+ }
+ 
+ /*
+  * ql_process_comp_queue
+  *      Process completion queue entries.
+  *
+  * Input:
+  *      arg:    adapter state pointer.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static void
+ ql_process_comp_queue(void *arg)
+ {
+         ql_srb_t                *sp;
+         ql_adapter_state_t      *ha = arg;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         COMP_Q_LOCK(ha);
+ 
+         /* process completion queue items */
+         while (ha->comp_q.first != NULL) {
+                 sp = (ha->comp_q.first)->base_address;
+                 QL_PRINT_3(ha, "sending comp=0x%p\n", (void *)sp);
+                 /* Remove command from completion queue */
+                 ql_remove_link(&ha->comp_q, &sp->cmd);
+                 COMP_Q_UNLOCK(ha);
+                 (sp->pkt->pkt_comp)(sp->pkt);
+                 COMP_Q_LOCK(ha);
+         }
+ 
+         COMP_Q_UNLOCK(ha);
+ 
+         QL_PRINT_3(ha, "done\n");
+ }
+ 
+ /*
+  * ql_abort_io
+  *      Abort I/O.
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *      sp:     SRB pointer.
+  *
+  * Returns:
+  *      ql local function return status code.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static int
+ ql_abort_io(ql_adapter_state_t *vha, ql_srb_t *sp)
+ {
+         ql_link_t               *link;
+         ql_srb_t                *sp2;
+         ql_tgt_t                *tq;
+         ql_lun_t                *lq;
+         int                     rval = QL_FUNCTION_FAILED;
+         ql_adapter_state_t      *ha = vha->pha;
+ 
+         QL_PRINT_10(ha, "started, sp=%ph, handle=%xh\n", (void *)sp,
+             sp->handle);
+ 
+         if ((lq = sp->lun_queue) != NULL) {
+                 tq = lq->target_queue;
          } else {
!                 tq = NULL;
          }
+ 
+         /* Acquire target queue lock. */
+         if (tq) {
+                 DEVICE_QUEUE_LOCK(tq);
+         }
+         REQUEST_RING_LOCK(ha);
+ 
+         /* If command not already started. */
+         if (!(sp->flags & SRB_ISP_STARTED)) {
+                 rval = QL_FUNCTION_PARAMETER_ERROR;
+ 
+                 /* Check pending queue for command. */
+                 for (link = ha->pending_cmds.first; link != NULL;
+                     link = link->next) {
+                         sp2 = link->base_address;
+                         if (sp2 == sp) {
+                                 rval = QL_SUCCESS;
+                                 /* Remove srb from pending command queue */
+                                 ql_remove_link(&ha->pending_cmds, &sp->cmd);
                                  break;
                          }
!                 }
! 
!                 if (link == NULL && lq) {
!                         /* Check for cmd on device queue. */
!                         for (link = lq->cmd.first; link != NULL;
!                             link = link->next) {
!                                 sp2 = link->base_address;
!                                 if (sp2 == sp) {
!                                         rval = QL_SUCCESS;
!                                         /* Remove srb from device queue. */
!                                         ql_remove_link(&lq->cmd, &sp->cmd);
!                                         sp->flags &= ~SRB_IN_DEVICE_QUEUE;
                                          break;
!                                 }
!                         }
!                 }
!         }
! 
!         REQUEST_RING_UNLOCK(ha);
!         if (tq) {
!                 DEVICE_QUEUE_UNLOCK(tq);
!         }
! 
!         if (sp->flags & SRB_ISP_COMPLETED || rval == QL_SUCCESS) {
!                 rval = QL_SUCCESS;
!         } else {
!                 uint32_t        index;
! 
!                 INTR_LOCK(ha);
!                 sp->flags |= SRB_ABORTING;
!                 if (sp->handle != 0) {
!                         index = sp->handle & OSC_INDEX_MASK;
!                         if (ha->outstanding_cmds[index] == sp) {
!                                 ha->outstanding_cmds[index] =
!                                     QL_ABORTED_SRB(ha);
!                         }
!                         /* Decrement outstanding commands on device. */
!                         if (tq != NULL && tq->outcnt != 0) {
!                                 tq->outcnt--;
!                         }
!                         if (lq != NULL && sp->flags & SRB_FCP_CMD_PKT &&
!                             lq->lun_outcnt != 0) {
!                                 lq->lun_outcnt--;
!                         }
!                         /* Remove command from watchdog queue. */
!                         if (sp->flags & SRB_WATCHDOG_ENABLED) {
!                                 if (tq != NULL) {
!                                         ql_remove_link(&tq->wdg, &sp->wdg);
!                                 }
!                                 sp->flags &= ~SRB_WATCHDOG_ENABLED;
!                         }
!                         INTR_UNLOCK(ha);
!                         (void) ql_abort_command(ha, sp);
!                         sp->handle = 0;
!                 } else {
!                         INTR_UNLOCK(ha);
!                 }
!                 rval = QL_SUCCESS;
!         }
! 
!         if (rval != QL_SUCCESS) {
!                 EL(ha, "sp=%p not aborted=%xh\n", (void *)sp, rval);
!         } else {
!                 /*EMPTY*/
!                 QL_PRINT_10(ha, "done\n");
!         }
!         return (rval);
! }
! 
! /*
!  *  ql_idc
!  *      Inter driver communication thread.
!  *
!  * Input:
!  *      ha = adapter state pointer.
!  *
!  * Context:
!  *      Kernel context.
!  */
! static void
! ql_idc(ql_adapter_state_t *ha)
! {
!         int             rval;
!         uint32_t        timer = 300;
! 
!         QL_PRINT_10(ha, "started\n");
! 
!         for (;;) {
!                 /* IDC Stall needed. */
!                 if (ha->flags & IDC_STALL_NEEDED) {
!                         ADAPTER_STATE_LOCK(ha);
!                         ha->flags &= ~IDC_STALL_NEEDED;
                          ADAPTER_STATE_UNLOCK(ha);
                          TASK_DAEMON_LOCK(ha);
                          ha->task_daemon_flags |= DRIVER_STALL;
                          TASK_DAEMON_UNLOCK(ha);
!                         if (LOOP_READY(ha)) {
!                                 if ((ha->idc_mb[1] & IDC_TIMEOUT_MASK) <
!                                     IDC_TIMEOUT_MASK) {
!                                         ha->idc_mb[1] = (uint16_t)
!                                             (ha->idc_mb[1] | IDC_TIMEOUT_MASK);
!                                         rval = ql_idc_time_extend(ha);
!                                         if (rval != QL_SUCCESS) {
!                                                 EL(ha, "idc_time_extend status"
!                                                     "=%xh\n", rval);
!                                         }
!                                 }
                                  (void) ql_wait_outstanding(ha);
                          }
!                 }
! 
!                 /* IDC ACK needed. */
!                 if (ha->flags & IDC_ACK_NEEDED) {
!                         ADAPTER_STATE_LOCK(ha);
!                         ha->flags &= ~IDC_ACK_NEEDED;
!                         ADAPTER_STATE_UNLOCK(ha);
                          rval = ql_idc_ack(ha);
                          if (rval != QL_SUCCESS) {
!                                 EL(ha, "idc_ack status=%xh\n", rval);
!                                 ADAPTER_STATE_LOCK(ha);
!                                 ha->flags |= IDC_RESTART_NEEDED;
!                                 ADAPTER_STATE_UNLOCK(ha);
                          }
                  }
! 
!                 /* IDC Restart needed. */
!                 if (timer-- == 0 || ha->flags & ADAPTER_SUSPENDED ||
!                     (ha->flags & IDC_RESTART_NEEDED &&
!                     !(ha->flags & LOOPBACK_ACTIVE))) {
                          ADAPTER_STATE_LOCK(ha);
!                         ha->flags &= ~(IDC_RESTART_NEEDED | IDC_STALL_NEEDED |
!                             IDC_ACK_NEEDED);
                          ADAPTER_STATE_UNLOCK(ha);
                          TASK_DAEMON_LOCK(ha);
                          ha->task_daemon_flags &= ~DRIVER_STALL;
                          TASK_DAEMON_UNLOCK(ha);
+                         if (LOOP_READY(ha)) {
                                  ql_restart_queues(ha);
+                         }
+                         break;
+                 }
+                 delay(10);
+         }
+ 
+         QL_PRINT_10(ha, "done\n");
+ }
+ 
+ /*
+  * ql_get_lun_addr
+  *      get the lunslun address.
+  *
+  * Input:
+  *      tq:     target queue pointer.
+  *      lun:    the lun number.
+  *
+  * Returns:
+  *      the lun address.
+  *
+  * Context:
+  *      Interrupt or Kernel context, no mailbox commands allowed.
+  */
+ uint64_t
+ ql_get_lun_addr(ql_tgt_t *tq, uint16_t lun)
+ {
+         ql_lun_t                *lq;
+         ql_link_t               *link = NULL;
+         uint64_t                lun_addr = 0;
+         fcp_ent_addr_t          *fcp_ent_addr = (fcp_ent_addr_t *)&lun_addr;
+ 
+         /* If the lun queue exists */
+         if (tq) {
+                 for (link = tq->lun_queues.first; link != NULL;
+                     link = link->next) {
+                         lq = link->base_address;
+                         if (lq->lun_no == lun) {
+                                 break;
+                         }
+                 }
+         }
+         if (link == NULL) {
+                 /* create an fcp_ent_addr from the lun number */
+                 if (MSB(lun)) {
+                         fcp_ent_addr->ent_addr_0 = CHAR_TO_SHORT(lobyte(lun),
+                             (hibyte(lun) | QL_LUN_AM_FLAT));
                  } else {
!                         fcp_ent_addr->ent_addr_0 = CHAR_TO_SHORT(lobyte(lun),
!                             hibyte(lun));
                  }
          } else {
!                 lun_addr = lq->lun_addr;
          }
+ 
+         return (lun_addr);
+ }
+ 
+ 
+ /*
+  * ql_83xx_binary_fw_dump
+  *
+  * Input:
+  *      ha:     adapter state pointer.
+  *      fw:     firmware dump context pointer.
+  *
+  * Returns:
+  *      ql local function return status code.
+  *
+  * Context:
+  *      Interrupt or Kernel context, no mailbox commands allowed.
+  */
+ static int
+ ql_83xx_binary_fw_dump(ql_adapter_state_t *ha, ql_83xx_fw_dump_t *fw)
+ {
+         uint32_t        *reg32, cnt, *w32ptr, index, *dp;
+         void            *bp;
+         clock_t         timer;
+         int             rv, rval = QL_SUCCESS;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         fw->req_q_size[0] = ha->req_q[0]->req_ring.size;
+         if (ha->req_q[1] != NULL) {
+                 fw->req_q_size[1] = ha->req_q[1]->req_ring.size;
+         }
+         fw->rsp_q_size = ha->rsp_queues[0]->rsp_ring.size * ha->rsp_queues_cnt;
+ 
+         fw->hccr = RD32_IO_REG(ha, hccr);
+         fw->r2h_status = RD32_IO_REG(ha, risc2host);
+         fw->aer_ues = ql_pci_config_get32(ha, 0x104);
+ 
+         /* Disable ISP interrupts. */
+         ql_disable_intr(ha);
+ 
+         /* Pause RISC. */
+         if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
+                 WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
+                 for (timer = 30000;
+                     (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0 &&
+                     rval == QL_SUCCESS; timer--) {
+                         if (timer) {
+                                 drv_usecwait(100);
+                                 if (timer % 10000 == 0) {
+                                         EL(ha, "risc pause %d\n", timer);
+                                 }
+                         } else {
+                                 EL(ha, "risc pause timeout\n");
+                                 rval = QL_FUNCTION_TIMEOUT;
+                         }
+                 }
+         }
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x6000);
+         WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0);
+         WRT_REG_DWORD(ha, ha->iobase + 0xcc, 0);
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x6010);
+         WRT_REG_DWORD(ha, ha->iobase + 0xd4, 0);
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x0F70);
+         WRT_REG_DWORD(ha, ha->iobase + 0xf0, 0x60000000);
+ 
+         /* Host Interface registers */
+ 
+         /* HostRisc registers. */
+         WRT32_IO_REG(ha, io_base_addr, 0x7000);
+         bp = ql_read_regs(ha, fw->hostrisc_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7010);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7040);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* PCIe registers. */
+         WRT32_IO_REG(ha, io_base_addr, 0x7c00);
+         WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x1);
+         bp = ql_read_regs(ha, fw->pcie_reg, ha->iobase + 0xC4,
+             3, 32);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 1, 32);
+         WRT_REG_DWORD(ha, ha->iobase + 0xc0, 0x0);
+ 
+         /* Host interface registers. */
+         (void) ql_read_regs(ha, fw->host_reg, ha->iobase,
+             sizeof (fw->host_reg) / 4, 32);
+ 
+         /* Shadow registers. */
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x0F70);
+         RD32_IO_REG(ha, io_base_addr);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0000000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[0] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0100000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[1] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0200000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[2] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0300000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[3] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0400000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[4] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0500000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[5] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0600000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[6] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0700000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[7] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0800000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[8] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0900000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[9] = RD_REG_DWORD(ha, reg32);
+ 
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xF0);
+         WRT_REG_DWORD(ha, reg32, 0xB0A00000);
+         reg32 = (uint32_t *)((caddr_t)ha->iobase + 0xFC);
+         fw->shadow_reg[0xa] = RD_REG_DWORD(ha, reg32);
+ 
+         /* RISC I/O register. */
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x0010);
+         (void) ql_read_regs(ha, &fw->risc_io, ha->iobase + 0xC0,
+             1, 32);
+ 
+         /* Mailbox registers. */
+ 
+         (void) ql_read_regs(ha, fw->mailbox_reg, ha->iobase + 0x80,
+             sizeof (fw->mailbox_reg) / 2, 16);
+ 
+         /* Transfer sequence registers. */
+ 
+         /* XSEQ GP */
+         WRT32_IO_REG(ha, io_base_addr, 0xBE00);
+         bp = ql_read_regs(ha, fw->xseq_gp_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBE10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBE20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBE30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBE40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBE50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBE60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBE70);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF00);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBF70);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* XSEQ-0 */
+         WRT32_IO_REG(ha, io_base_addr, 0xBFC0);
+         bp = ql_read_regs(ha, fw->xseq_0_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBFD0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xBFE0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* XSEQ-1 */
+         WRT32_IO_REG(ha, io_base_addr, 0xBFF0);
+         (void) ql_read_regs(ha, fw->xseq_1_reg, ha->iobase + 0xC0,
+             16, 32);
+ 
+         /* XSEQ-2 */
+         WRT32_IO_REG(ha, io_base_addr, 0xBEF0);
+         (void) ql_read_regs(ha, fw->xseq_2_reg, ha->iobase + 0xC0,
+             16, 32);
+ 
+         /* Receive sequence registers. */
+ 
+         /* RSEQ GP */
+         WRT32_IO_REG(ha, io_base_addr, 0xFE00);
+         bp = ql_read_regs(ha, fw->rseq_gp_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFE10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFE20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFE30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFE40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFE50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFE60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFE70);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF00);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFF70);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* RSEQ-0 */
+         WRT32_IO_REG(ha, io_base_addr, 0xFFC0);
+         bp = ql_read_regs(ha, fw->rseq_0_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xFFD0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* RSEQ-1 */
+         WRT32_IO_REG(ha, io_base_addr, 0xFFE0);
+         (void) ql_read_regs(ha, fw->rseq_1_reg, ha->iobase + 0xC0,
+             sizeof (fw->rseq_1_reg) / 4, 32);
+ 
+         /* RSEQ-2 */
+         WRT32_IO_REG(ha, io_base_addr, 0xFFF0);
+         (void) ql_read_regs(ha, fw->rseq_2_reg, ha->iobase + 0xC0,
+             sizeof (fw->rseq_2_reg) / 4, 32);
+ 
+         /* RSEQ-3 */
+         WRT32_IO_REG(ha, io_base_addr, 0xFEF0);
+         (void) ql_read_regs(ha, fw->rseq_3_reg, ha->iobase + 0xC0,
+             sizeof (fw->rseq_3_reg) / 4, 32);
+ 
+         /* Auxiliary sequencer registers. */
+ 
+         /* ASEQ GP */
+         WRT32_IO_REG(ha, io_base_addr, 0xB000);
+         bp = ql_read_regs(ha, fw->aseq_gp_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB010);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB020);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB030);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB040);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB050);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB060);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB070);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB100);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB110);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB120);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB130);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB140);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB150);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB160);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB170);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* ASEQ-0 */
+         WRT32_IO_REG(ha, io_base_addr, 0xB0C0);
+         bp = ql_read_regs(ha, fw->aseq_0_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0xB0D0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* ASEQ-1 */
+         WRT32_IO_REG(ha, io_base_addr, 0xB0E0);
+         (void) ql_read_regs(ha, fw->aseq_1_reg, ha->iobase + 0xC0,
+             16, 32);
+ 
+         /* ASEQ-2 */
+         WRT32_IO_REG(ha, io_base_addr, 0xB0F0);
+         (void) ql_read_regs(ha, fw->aseq_2_reg, ha->iobase + 0xC0,
+             16, 32);
+ 
+         /* ASEQ-3 */
+         WRT32_IO_REG(ha, io_base_addr, 0xB1F0);
+         (void) ql_read_regs(ha, fw->aseq_3_reg, ha->iobase + 0xC0,
+             16, 32);
+ 
+         /* Command DMA registers. */
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x7100);
+         bp = ql_read_regs(ha, fw->cmd_dma_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7120);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7130);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x71f0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* Queues. */
+ 
+         /* RequestQ0 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7200);
+         bp = ql_read_regs(ha, fw->req0_dma_reg, ha->iobase + 0xC0,
+             8, 32);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xE4, 7, 32);
+ 
+         /* ResponseQ0 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7300);
+         bp = ql_read_regs(ha, fw->resp0_dma_reg, ha->iobase + 0xC0,
+             8, 32);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xE4, 7, 32);
+ 
+         /* RequestQ1 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7400);
+         bp = ql_read_regs(ha, fw->req1_dma_reg, ha->iobase + 0xC0,
+             8, 32);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xE4, 7, 32);
+ 
+         /* Transmit DMA registers. */
+ 
+         /* XMT0 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7600);
+         bp = ql_read_regs(ha, fw->xmt0_dma_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7610);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* XMT1 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7620);
+         bp = ql_read_regs(ha, fw->xmt1_dma_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7630);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* XMT2 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7640);
+         bp = ql_read_regs(ha, fw->xmt2_dma_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7650);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* XMT3 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7660);
+         bp = ql_read_regs(ha, fw->xmt3_dma_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7670);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* XMT4 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7680);
+         bp = ql_read_regs(ha, fw->xmt4_dma_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7690);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* XMT Common */
+         WRT32_IO_REG(ha, io_base_addr, 0x76A0);
+         (void) ql_read_regs(ha, fw->xmt_data_dma_reg,
+             ha->iobase + 0xC0, sizeof (fw->xmt_data_dma_reg) / 4, 32);
+ 
+         /* Receive DMA registers. */
+ 
+         /* RCVThread0 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7700);
+         bp = ql_read_regs(ha, fw->rcvt0_data_dma_reg,
+             ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7710);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* RCVThread1 */
+         WRT32_IO_REG(ha, io_base_addr, 0x7720);
+         bp = ql_read_regs(ha, fw->rcvt1_data_dma_reg,
+             ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7730);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* RISC registers. */
+ 
+         /* RISC GP */
+         WRT32_IO_REG(ha, io_base_addr, 0x0F00);
+         bp = ql_read_regs(ha, fw->risc_gp_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x0F10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x0F20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x0F30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x0F40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x0F50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x0F60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x0F70);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* Local memory controller (LMC) registers. */
+ 
+         /* LMC */
+         WRT32_IO_REG(ha, io_base_addr, 0x3000);
+         bp = ql_read_regs(ha, fw->lmc_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x3010);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x3020);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x3030);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x3040);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x3050);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x3060);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x3070);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* Fibre Protocol Module registers. */
+ 
+         /* FPM hardware */
+         WRT32_IO_REG(ha, io_base_addr, 0x4000);
+         bp = ql_read_regs(ha, fw->fpm_hdw_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4010);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4020);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4030);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4040);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4050);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4060);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4070);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4080);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x4090);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x40A0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x40B0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x40C0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x40D0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x40E0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x40F0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* Pointer arrays registers */
+ 
+         /* RQ0 Array registers. */
+         WRT32_IO_REG(ha, io_base_addr, 0x5C00);
+         bp = ql_read_regs(ha, fw->rq0_array_reg, ha->iobase + 0xC0,
+             16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C70);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C80);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5C90);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5CA0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5CB0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5CC0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5CD0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5CE0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5CF0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* RQ1 Array registers. */
+         WRT32_IO_REG(ha, io_base_addr, 0x5D00);
+         bp = ql_read_regs(ha, fw->rq1_array_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D70);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D80);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5D90);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5DA0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5DB0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5DC0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5DD0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5DE0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5DF0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* RP0 Array registers. */
+         WRT32_IO_REG(ha, io_base_addr, 0x5E00);
+         bp = ql_read_regs(ha, fw->rp0_array_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E70);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E80);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5E90);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5EA0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5EB0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5EC0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5ED0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5EE0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5EF0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* RP1 Array registers. */
+         WRT32_IO_REG(ha, io_base_addr, 0x5F00);
+         bp = ql_read_regs(ha, fw->rp1_array_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F10);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F20);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F30);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F40);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F50);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F60);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F70);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F80);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5F90);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5FA0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5FB0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5FC0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5FD0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5FE0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x5FF0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* AT0 Array Registers */
+         WRT32_IO_REG(ha, io_base_addr, 0x7080);
+         bp = ql_read_regs(ha, fw->ato_array_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x7090);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x70A0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x70B0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x70C0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x70D0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x70E0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x70F0);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* I/O queue control registers */
+ 
+         /* Queue Control Registers. */
+         WRT32_IO_REG(ha, io_base_addr, 0x7800);
+         (void) ql_read_regs(ha, fw->queue_control_reg, ha->iobase + 0xC0,
+             16, 32);
+ 
+         /* Frame Buffer registers. */
+ 
+         /* FB hardware */
+         WRT32_IO_REG(ha, io_base_addr, 0x6000);
+         bp = ql_read_regs(ha, fw->fb_hdw_reg, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6010);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6020);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6030);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6040);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6060);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6070);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6100);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6130);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6150);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6170);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6190);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x61B0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x61C0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6530);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6540);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6550);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6560);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6570);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6580);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6590);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x65A0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x65B0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x65C0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x65D0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x65E0);
+         bp = ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+         WRT32_IO_REG(ha, io_base_addr, 0x6F00);
+         (void) ql_read_regs(ha, bp, ha->iobase + 0xC0, 16, 32);
+ 
+         /* Get the Queue Pointers */
+         dp = fw->req_rsp_ext_mem;
+         for (index = 0; index < ha->rsp_queues_cnt; index++) {
+                 if (index == 0) {
+                         *dp = RD32_MBAR_REG(ha, ha->req_q[0]->mbar_req_in);
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                         *dp = RD32_MBAR_REG(ha, ha->req_q[0]->mbar_req_out);
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                 } else if (index == 1) {
+                         *dp = RD32_MBAR_REG(ha, ha->req_q[1]->mbar_req_in);
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                         *dp = RD32_MBAR_REG(ha, ha->req_q[1]->mbar_req_out);
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                 } else {
+                         *dp++ = 0;
+                         *dp++ = 0;
+                 }
+                 *dp = RD32_MBAR_REG(ha, ha->rsp_queues[index]->mbar_rsp_in);
+                 LITTLE_ENDIAN_32(dp);
+                 dp++;
+                 *dp = RD32_MBAR_REG(ha, ha->rsp_queues[index]->mbar_rsp_out);
+                 LITTLE_ENDIAN_32(dp);
+                 dp++;
+         }
+ 
+         /* Get the request queue */
+         (void) ddi_dma_sync(ha->req_q[0]->req_ring.dma_handle, 0, 0,
+             DDI_DMA_SYNC_FORCPU);
+         w32ptr = (uint32_t *)ha->req_q[0]->req_ring.bp;
+         for (cnt = 0; cnt < fw->req_q_size[0] / 4; cnt++) {
+                 *dp = *w32ptr++;
+                 LITTLE_ENDIAN_32(dp);
+                 dp++;
+         }
+         if (ha->req_q[1] != NULL) {
+                 (void) ddi_dma_sync(ha->req_q[1]->req_ring.dma_handle, 0, 0,
+                     DDI_DMA_SYNC_FORCPU);
+                 w32ptr = (uint32_t *)ha->req_q[1]->req_ring.bp;
+                 for (cnt = 0; cnt < fw->req_q_size[1] / 4; cnt++) {
+                         *dp = *w32ptr++;
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                 }
+         }
+ 
+         /* Get the response queues */
+         for (index = 0; index < ha->rsp_queues_cnt; index++) {
+                 (void) ddi_dma_sync(ha->rsp_queues[index]->rsp_ring.dma_handle,
+                     0, 0, DDI_DMA_SYNC_FORCPU);
+                 w32ptr = (uint32_t *)ha->rsp_queues[index]->rsp_ring.bp;
+                 for (cnt = 0; cnt < ha->rsp_queues[index]->rsp_ring.size / 4;
+                     cnt++) {
+                         *dp = *w32ptr++;
+                         LITTLE_ENDIAN_32(dp);
+                         dp++;
+                 }
+         }
+ 
+         /* Reset RISC. */
+         ql_reset_chip(ha);
+ 
+         /* Code RAM. */
+         rv = ql_read_risc_ram(ha, 0x20000, sizeof (fw->code_ram) / 4,
+             fw->code_ram);
+         if (rval == QL_SUCCESS) {
+                 rval = rv;
+         }
+         rv = ql_read_risc_ram(ha, 0x100000,
+             ha->fw_ext_memory_size / 4, dp);
+         if (rval == QL_SUCCESS) {
+                 rval = rv;
+         }
+ 
+         /* Get the extended trace buffer */
+         if (ha->fwexttracebuf.dma_handle != NULL) {
+                 /* Sync DMA buffer. */
+                 (void) ddi_dma_sync(ha->fwexttracebuf.dma_handle, 0,
+                     FWEXTSIZE, DDI_DMA_SYNC_FORCPU);
+ 
+                 w32ptr = ha->fwexttracebuf.bp;
+                 for (cnt = 0; cnt < FWEXTSIZE / 4; cnt++) {
+                         fw->ext_trace_buf[cnt] = *w32ptr++;
+                 }
+         }
+ 
+         /* Get the FC event trace buffer */
+         if (ha->fwfcetracebuf.dma_handle != NULL) {
+                 /* Sync DMA buffer. */
+                 (void) ddi_dma_sync(ha->fwfcetracebuf.dma_handle, 0,
+                     FWFCESIZE, DDI_DMA_SYNC_FORCPU);
+ 
+                 w32ptr = ha->fwfcetracebuf.bp;
+                 for (cnt = 0; cnt < FWFCESIZE / 4; cnt++) {
+                         fw->fce_trace_buf[cnt] = *w32ptr++;
+                 }
+         }
+ 
+         if (rval != QL_SUCCESS) {
+                 EL(ha, "failed, rval = %xh\n", rval);
+         } else {
+                 /*EMPTY*/
+                 QL_PRINT_10(ha, "done\n");
+         }
+         return (QL_SUCCESS);
+ }
+ 
+ /*
+  * ql_83xx_ascii_fw_dump
+  *      Converts ISP83xx firmware binary dump to ascii.
+  *
+  * Input:
+  *      ha = adapter state pointer.
+  *      bptr = buffer pointer.
+  *
+  * Returns:
+  *      Amount of data buffer used.
+  *
+  * Context:
+  *      Kernel context.
+  */
+ static size_t
+ ql_83xx_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
+ {
+         uint32_t                cnt, cnt1, len, *dp, *dp2;
+         caddr_t                 bp = bufp;
+         ql_83xx_fw_dump_t       *fw = ha->ql_dump_ptr;
+ 
+         QL_PRINT_3(ha, "started\n");
+ 
+         if ((len = ha->risc_dump_size) == 0) {
+                 QL_PRINT_10(ha, "no buffer\n");
+                 return (0);
+         }
+         (void) snprintf(bp, len, "\nISP FW Version %d.%02d.%02d Attributes "
+             "%X\n", ha->fw_major_version, ha->fw_minor_version,
+             ha->fw_subminor_version, ha->fw_attributes);
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+ 
+         (void) snprintf(bp, len, "\nHCCR Register\n%08x\n", fw->hccr);
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+ 
+         (void) snprintf(bp, len, "\nR2H Status Register\n%08x\n",
+             fw->r2h_status);
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+ 
+         (void) snprintf(bp, len,
+             "\nAER Uncorrectable Error Status Register\n%08x\n", fw->aer_ues);
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+ 
+         (void) snprintf(bp, len, "\nHostRisc Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->hostrisc_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->hostrisc_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nPCIe Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->pcie_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->pcie_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         dp = fw->req_rsp_ext_mem;
+         for (cnt = 0; cnt < ha->rsp_queues_cnt; cnt++) {
+                 (void) snprintf(bp, len, "\n\nQueue Pointers #%d:\n", cnt);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+                 for (cnt1 = 0; cnt1 < 4; cnt1++) {
+                         (void) snprintf(bp, len, "%08x ", *dp++);
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nHost Interface Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->host_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->host_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nShadow Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->shadow_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->shadow_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRISC IO Register\n%08x", fw->risc_io);
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+ 
+         (void) snprintf(bp, len, "\n\nMailbox Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->mailbox_reg) / 2; cnt++) {
+                 if (cnt % 16 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%04x ", fw->mailbox_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXSEQ GP Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xseq_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xseq_gp_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXSEQ-0 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xseq_0_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xseq_0_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXSEQ-1 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xseq_1_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xseq_1_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXSEQ-2 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xseq_2_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xseq_2_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRSEQ GP Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->rseq_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rseq_gp_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRSEQ-0 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->rseq_0_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rseq_0_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRSEQ-1 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->rseq_1_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rseq_1_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRSEQ-2 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->rseq_2_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rseq_2_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRSEQ-3 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->rseq_3_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rseq_3_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nASEQ GP Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->aseq_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->aseq_gp_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nASEQ-0 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->aseq_0_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->aseq_0_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nASEQ-1 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->aseq_1_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->aseq_1_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nASEQ-2 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->aseq_2_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->aseq_2_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nASEQ-3 Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->aseq_3_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->aseq_3_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nCommand DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->cmd_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->cmd_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRequest0 Queue DMA Channel Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->req0_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->req0_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nResponse0 Queue DMA Channel Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->resp0_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->resp0_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRequest1 Queue DMA Channel Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->req1_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->req1_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXMT0 Data DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xmt0_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xmt0_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXMT1 Data DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xmt1_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xmt1_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXMT2 Data DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xmt2_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xmt2_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXMT3 Data DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xmt3_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xmt3_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXMT4 Data DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xmt4_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xmt4_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nXMT Data DMA Common Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->xmt_data_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->xmt_data_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRCV Thread 0 Data DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->rcvt0_data_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rcvt0_data_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRCV Thread 1 Data DMA Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->rcvt1_data_dma_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rcvt1_data_dma_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRISC GP Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->risc_gp_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->risc_gp_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nLMC Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->lmc_reg) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->lmc_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nFPM Hardware Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->fpm_hdw_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->fpm_hdw_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRQ0 Array Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->rq0_array_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rq0_array_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRQ1 Array Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->rq1_array_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rq1_array_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRP0 Array Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->rp0_array_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rp0_array_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nRP1 Array Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->rp1_array_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->rp1_array_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nAT0 Array Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->ato_array_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->ato_array_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nQueue Control Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->queue_control_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->queue_control_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nFB Hardware Registers");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         cnt1 = (uint32_t)(sizeof (fw->fb_hdw_reg));
+         for (cnt = 0; cnt < cnt1 / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n");
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->fb_hdw_reg[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nCode RAM");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         for (cnt = 0; cnt < sizeof (fw->code_ram) / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n%08x: ", cnt + 0x20000);
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", fw->code_ram[cnt]);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\nExternal Memory");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+         dp = (uint32_t *)((caddr_t)fw->req_rsp_ext_mem + fw->req_q_size[0] +
+             fw->req_q_size[1] + fw->rsp_q_size + (ha->rsp_queues_cnt * 16));
+         for (cnt = 0; cnt < ha->fw_ext_memory_size / 4; cnt++) {
+                 if (cnt % 8 == 0) {
+                         (void) snprintf(bp, len, "\n%08x: ", cnt + 0x100000);
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+                 (void) snprintf(bp, len, "%08x ", *dp++);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+         }
+ 
+         (void) snprintf(bp, len, "\n\n[<==END] ISP Debug Dump");
+         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                 return (strlen(bufp));
+         }
+ 
+         dp = fw->req_rsp_ext_mem + (ha->rsp_queues_cnt * 4);
+         for (cnt = 0; cnt < 2 && fw->req_q_size[cnt]; cnt++) {
+                 dp2 = dp;
+                 for (cnt1 = 0; cnt1 < fw->req_q_size[cnt] / 4; cnt1++) {
+                         if (*dp2++) {
                                  break;
                          }
+                 }
+                 if (cnt1 == fw->req_q_size[cnt] / 4) {
+                         dp = dp2;
+                         continue;
+                 }
+                 (void) snprintf(bp, len, "\n\nRequest Queue\nQueue %d:", cnt);
+                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                         return (strlen(bufp));
+                 }
+                 for (cnt1 = 0; cnt1 < fw->req_q_size[cnt] / 4; cnt1++) {
+                         if (cnt1 % 8 == 0) {
+                                 (void) snprintf(bp, len, "\n%08x: ", cnt1);
+                                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                         return (strlen(bufp));
+                                 }
+                         }
+                         (void) snprintf(bp, len, "%08x ", *dp++);
+                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
+                                 return (strlen(bufp));
+                         }
+                 }
+         }
+ 
+         for (cnt = 0; cnt < ha->rsp_queues_cnt; cnt++) {
+                 dp2 = dp;
+                 for (cnt1 = 0; cnt1 < ha->rsp_queues[cnt]->rsp_ring.size / 4;
+                     cnt1++) {
+                         if (*dp2++) {
                                  break;
!                         }
!                 }
!                 if (cnt1 == ha->rsp_queues[cnt]->rsp_ring.size / 4) {
!                         dp = dp2;
!                         continue;
!                 }
!                 (void) snprintf(bp, len, "\n\nResponse Queue\nQueue %d:", cnt);
!                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                         return (strlen(bufp));
!                 }
!                 for (cnt1 = 0; cnt1 < ha->rsp_queues[cnt]->rsp_ring.size / 4;
!                     cnt1++) {
!                         if (cnt1 % 8 == 0) {
!                                 (void) snprintf(bp, len, "\n%08x: ", cnt1);
!                                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                                         return (strlen(bufp));
!                                 }
!                         }
!                         (void) snprintf(bp, len, "%08x ", *dp++);
!                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                                 return (strlen(bufp));
!                         }
!                 }
!         }
! 
!         if (ha->fwexttracebuf.dma_handle != NULL) {
!                 uint32_t        cnt_b;
!                 uint64_t        w64 = (uintptr_t)ha->fwexttracebuf.bp;
! 
!                 (void) snprintf(bp, len, "\n\nExtended Trace Buffer Memory");
!                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                         return (strlen(bufp));
!                 }
!                 /* show data address as a byte address, data as long words */
!                 for (cnt = 0; cnt < FWEXTSIZE / 4; cnt++) {
!                         cnt_b = cnt * 4;
!                         if (cnt_b % 32 == 0) {
!                                 (void) snprintf(bp, len, "\n%08x: ",
!                                     (int)(w64 + cnt_b));
!                                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                                         return (strlen(bufp));
!                                 }
!                         }
!                         (void) snprintf(bp, len, "%08x ",
!                             fw->ext_trace_buf[cnt]);
!                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                                 return (strlen(bufp));
!                         }
!                 }
!         }
! 
!         if (ha->fwfcetracebuf.dma_handle != NULL) {
!                 uint32_t        cnt_b;
!                 uint64_t        w64 = (uintptr_t)ha->fwfcetracebuf.bp;
! 
!                 (void) snprintf(bp, len, "\n\nFC Event Trace Buffer Memory");
!                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                         return (strlen(bufp));
!                 }
!                 /* show data address as a byte address, data as long words */
!                 for (cnt = 0; cnt < FWFCESIZE / 4; cnt++) {
!                         cnt_b = cnt * 4;
!                         if (cnt_b % 32 == 0) {
!                                 (void) snprintf(bp, len, "\n%08x: ",
!                                     (int)(w64 + cnt_b));
!                                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                                         return (strlen(bufp));
!                                 }
!                         }
!                         (void) snprintf(bp, len, "%08x ",
!                             fw->fce_trace_buf[cnt]);
!                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                                 return (strlen(bufp));
!                         }
!                 }
!         }
! 
!         QL_PRINT_10(ha, "done=%xh\n", strlen(bufp));
! 
!         return (strlen(bufp));
! }
! 
! 
! /*
!  * ql_str_ptr
!  *      Verifies buffer is not full
!  *
!  * Input:
!  *      ha:     adapter state pointer.
!  *      bp:     string buffer pointer
!  *      len:    buffer length
!  *
!  * Returns:
!  *      NULL = buffer full else adjusted buffer pointer
!  *
!  * Context:
!  *      Kernel context.
!  */
! /*ARGSUSED*/
! static caddr_t
! ql_str_ptr(ql_adapter_state_t *ha, caddr_t bp, uint32_t *len)
! {
!         uint32_t        i;
! 
!         i = strlen(bp);
!         if (i > *len || !(*len -= i)) {
!                 QL_PRINT_10(ha, "full buffer\n");
!                 return (NULL);
!         }
!         return (bp += i);
! }
! 
! /*
!  * ql_27xx_binary_fw_dump
!  *
!  * Input:
!  *      ha:     adapter state pointer.
!  *      dmp:    firmware dump pointer.
!  *
!  * Returns:
!  *      ql local function return status code.
!  *
!  * Context:
!  *      Interrupt or Kernel context, no mailbox commands allowed.
!  */
! static int
! ql_27xx_binary_fw_dump(ql_adapter_state_t *ha)
! {
!         ql_dmp_template_t       *template_buff;
!         int                     rval;
!         uint32_t                cnt, *dp, *bp, tsize;
! 
!         QL_PRINT_10(ha, "started\n");
! 
!         if (ha->dmp_template.dma_handle == NULL) {
!                 rval = CFG_IST(ha, CFG_LOAD_FLASH_FW) ?
!                     ql_2700_get_flash_dmp_template(ha) :
!                     ql_2700_get_module_dmp_template(ha);
!                 if (rval != QL_SUCCESS) {
!                         EL(ha, "no dump template, status=%xh\n", rval);
!                         return (QL_FUNCTION_PARAMETER_ERROR);
!                 }
!         }
!         template_buff = ha->dmp_template.bp;
!         tsize = template_buff->hdr.size_of_template;
! 
!         if (ha->md_capture_size == 0) {
!                 ha->ql_dump_ptr = kmem_zalloc(tsize, KM_NOSLEEP);
!                 if (ha->ql_dump_ptr == NULL) {
!                         QL_PRINT_10(ha, "done, failed alloc\n");
!                         return (QL_MEMORY_ALLOC_FAILED);
!                 }
!                 cnt = (uint32_t)(tsize / sizeof (uint32_t));
!                 dp = (uint32_t *)ha->ql_dump_ptr;
!                 bp = (uint32_t *)&template_buff->hdr;
!                 while (cnt--) {
!                         *dp++ = ddi_get32(ha->dmp_template.acc_handle, bp++);
!                 }
!                 ha->md_capture_size = ql_2700_dmp_parse_template(ha,
!                     (ql_dt_hdr_t *)ha->ql_dump_ptr, NULL, 0);
!                 kmem_free(ha->ql_dump_ptr, tsize);
!                 ha->ql_dump_ptr = NULL;
! 
!                 if (ha->md_capture_size == 0) {
!                         return (QL_MEMORY_ALLOC_FAILED);
!                 }
! 
!                 /*
!                  * Determine ascii dump file size
!                  * 2 ascii bytes per binary byte + a space and
!                  * a newline every 16 binary bytes
!                  */
!                 ha->risc_dump_size = ha->md_capture_size << 1;
!                 ha->risc_dump_size += ha->md_capture_size;
!                 ha->risc_dump_size += ha->md_capture_size / 16 + 1;
!                 QL_PRINT_10(ha, "md_capture_size=%xh, "
!                     "risc_dump_size=%xh\n", ha->md_capture_size,
!                     ha->risc_dump_size);
!         }
! 
!         ha->ql_dump_ptr = kmem_zalloc(ha->md_capture_size, KM_NOSLEEP);
!         if (ha->ql_dump_ptr == NULL) {
!                 QL_PRINT_10(ha, "done, failed alloc\n");
!                 return (QL_MEMORY_ALLOC_FAILED);
!         }
!         ha->ql_dump_size = ha->md_capture_size;
! 
!         /* Disable ISP interrupts. */
!         ql_disable_intr(ha);
! 
!         cnt = (uint32_t)(tsize / sizeof (uint32_t));
!         dp = (uint32_t *)ha->ql_dump_ptr;
!         bp = (uint32_t *)&template_buff->hdr;
!         while (cnt--) {
!                 *dp++ = ddi_get32(ha->dmp_template.acc_handle, bp++);
!         }
! 
!         (void) ql_2700_dmp_parse_template(ha,
!             (ql_dt_hdr_t *)ha->ql_dump_ptr,
!             (uint8_t *)dp, ha->ql_dump_size);
! 
! #ifdef _BIG_ENDIAN
!         cnt = (uint32_t)(tsize / sizeof (uint32_t));
!         dp = (uint32_t *)ha->ql_dump_ptr;
!         while (cnt--) {
!                 ql_chg_endian((uint8_t *)dp, 4);
!                 dp++;
!         }
! #endif
!         QL_PRINT_10(ha, "done\n");
!         return (QL_SUCCESS);
! }
! 
! /*
!  * ql_27xx_ascii_fw_dump
!  *      Converts ISP27xx firmware binary dump to ascii.
!  *
!  * Input:
!  *      ha:     port info pointer.
!  *      bptr:   buffer pointer.
!  *
!  * Returns:
!  *      Amount of data buffer used.
!  *
!  * Context:
!  *      Kernel context.
!  */
! static size_t
! ql_27xx_ascii_fw_dump(ql_adapter_state_t *ha, caddr_t bufp)
! {
!         uint32_t        cnt, len, dsize;
!         uint8_t         *fw;
!         caddr_t         bp;
! 
!         QL_PRINT_10(ha, "started\n");
! 
!         if ((len = ha->risc_dump_size) == 0) {
!                 QL_PRINT_10(ha, "no buffer\n");
!                 return (0);
!         }
! 
!         dsize = ha->ql_dump_size;
!         fw = (uint8_t *)ha->ql_dump_ptr;
!         bp = bufp;
! 
!         QL_PRINT_10(ha, "fw_dump_buffer=%ph, fw_bin_dump_size=%xh\n",
!             (void *)ha->ql_dump_ptr, ha->ql_dump_size);
! 
!         /*
!          * 2 ascii bytes per binary byte + a space and
!          * a newline every 16 binary bytes
!          */
!         cnt = 0;
!         while (cnt < dsize) {
!                 (void) snprintf(bp, len, "%02x ", *fw++);
!                 if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                         return (strlen(bufp));
!                 }
!                 if (++cnt % 16 == 0) {
!                         (void) snprintf(bp, len, "\n");
!                         if ((bp = ql_str_ptr(ha, bp, &len)) == NULL) {
!                                 return (strlen(bufp));
!                         }
!                 }
!         }
!         if (cnt % 16 != 0) {
!                 (void) snprintf(bp, len, "\n");
!                 bp = ql_str_ptr(ha, bp, &len);
!                 if (bp == NULL) {
!                         return (strlen(bufp));
!                 }
!         }
! 
!         QL_PRINT_10(ha, "done=%xh\n", strlen(bufp));
! 
!         return (strlen(bufp));
! }
! 
! /* ******************************************************************* */
! /* ********************* Dump Template Functions ********************* */
! /* ******************************************************************* */
! 
! /*
!  * ql_2700_get_module_dmp_template
!  *      Get dump template from firmware module
!  *
!  * Input:
!  *      ha:     adapter state pointer.
!  *
!  * Returns:
!  *      ql local function return status code.
!  *
!  * Context:
!  *      Kernel context.
!  */
! int
! ql_2700_get_module_dmp_template(ql_adapter_state_t *ha)
! {
!         int             rval;
!         uint32_t        word_count, cnt, *bp, *dp;
! 
!         QL_PRINT_10(ha, "started\n");
! 
!         if (ha->dmp_template.dma_handle != NULL) {
!                 return (QL_SUCCESS);
!         }
! 
!         if ((word_count = ha->risc_fw[2].length) == 0) {
!                 EL(ha, "no dump template, length=0\n");
!                 return (QL_FUNCTION_PARAMETER_ERROR);
!         }
! 
!         /* Allocate template buffer. */
!         ha->dmp_template.size = word_count << 2;
!         ha->dmp_template.type = LITTLE_ENDIAN_DMA;
!         ha->dmp_template.max_cookie_count = 1;
!         ha->dmp_template.alignment = 8;
!         rval = ql_alloc_phys(ha, &ha->dmp_template, KM_SLEEP);
!         if (rval != QL_SUCCESS) {
!                 EL(ha, "unable to allocate template buffer, "
!                     "status=%xh\n", rval);
!                 return (rval);
!         }
! 
!         /* Get big endian template. */
!         bp = ha->dmp_template.bp;
!         dp = (uint32_t *)ha->risc_fw[2].code;
!         for (cnt = 0; cnt < word_count; cnt++) {
!                 ddi_put32(ha->dmp_template.acc_handle, bp, *dp++);
!                 if (cnt > 6) {
!                         ql_chg_endian((uint8_t *)bp, 4);
!                 }
!                 bp++;
!         }
! 
!         QL_PRINT_10(ha, "done\n");
!         return (rval);
! }
! 
! /*
!  * ql_2700_get_flash_dmp_template
!  *      Get dump template from flash
!  *
!  * Input:
!  *      pi:     port info pointer.
!  *
!  * Returns:
!  *      ql local function return status code.
!  *
!  * Context:
!  *      Kernel context.
!  */
! int
! ql_2700_get_flash_dmp_template(ql_adapter_state_t *ha)
! {
!         int             rval;
!         uint32_t        word_count, cnt, *bp;
!         uint32_t        faddr = ha->flash_data_addr | ha->flash_fw_addr;
!         uint32_t        fdata = 0;
! 
!         QL_PRINT_10(ha, "started, fw_addr=%xh\n", ha->flash_fw_addr);
! 
!         if (ha->dmp_template.dma_handle != NULL) {
!                 ql_free_phys(ha, &ha->dmp_template);
!         }
! 
!         /* First array length */
!         rval = ql_24xx_read_flash(ha, faddr + 3, &fdata);
!         QL_PRINT_7(ha, "read_flash, fw_addr=0x%x, data=0x%x\n",
!             faddr + 3, fdata);
!         if (rval != QL_SUCCESS) {
!                 EL(ha, "2700_read_flash status=%xh\n", rval);
!                 return (rval);
!         }
!         if (fdata == 0 || fdata == 0xffffffff) {
!                 EL(ha, "Invalid first array length = %xh\n", fdata);
!                 return (QL_FUNCTION_PARAMETER_ERROR);
!         }
!         ql_chg_endian((uint8_t *)&fdata, 4);
!         QL_PRINT_7(ha, "First array length = %xh\n", fdata);
!         faddr += fdata;
! 
!         /* Second array length */
!         rval = ql_24xx_read_flash(ha, faddr + 3, &fdata);
!         QL_PRINT_7(ha, "read_flash, fw_addr=0x%x, data=0x%x\n",
!             faddr + 3, fdata);
!         if (rval != QL_SUCCESS) {
!                 EL(ha, "2700_read_flash status=%xh\n", rval);
!                 return (rval);
!         }
!         if (fdata == 0 || fdata == 0xffffffff) {
!                 EL(ha, "Invalid second array length = %xh\n", fdata);
!                 return (QL_FUNCTION_PARAMETER_ERROR);
!         }
!         ql_chg_endian((uint8_t *)&fdata, 4);
!         QL_PRINT_7(ha, "Second array length = %xh\n", fdata);
!         faddr += fdata;
! 
!         /* Third array length (dump template) */
!         rval = ql_24xx_read_flash(ha, faddr + 2, &fdata);
!         QL_PRINT_7(ha, "read_flash, fw_addr=0x%x, data=0x%x\n",
!             faddr + 2, fdata);
!         if (rval != QL_SUCCESS) {
!                 EL(ha, "2700_read_flash status=%xh\n", rval);
!                 return (rval);
!         }
!         if (fdata == 0 || fdata == 0xffffffff) {
!                 EL(ha, "Invalid third array length = %xh\n", fdata);
!                 return (QL_FUNCTION_PARAMETER_ERROR);
!         }
!         ql_chg_endian((uint8_t *)&fdata, 4);
!         QL_PRINT_7(ha, "Third array length = %xh\n", fdata);
!         word_count = fdata;
! 
!         /* Allocate template buffer. */
!         ha->dmp_template.size = word_count << 2;
!         ha->dmp_template.type = LITTLE_ENDIAN_DMA;
!         ha->dmp_template.max_cookie_count = 1;
!         ha->dmp_template.alignment = 8;
!         rval = ql_alloc_phys(ha, &ha->dmp_template, KM_SLEEP);
!         if (rval != QL_SUCCESS) {
!                 EL(ha, "unable to allocate template buffer, "
!                     "status=%xh\n", rval);
!                 return (rval);
!         }
! 
!         /* Get big endian template. */
!         bp = ha->dmp_template.bp;
!         for (cnt = 0; cnt < word_count; cnt++) {
!                 rval = ql_24xx_read_flash(ha, faddr++, &fdata);
!                 if (rval != QL_SUCCESS) {
!                         EL(ha, "2700_read_flash status=%xh\n", rval);
!                         ql_free_phys(ha, &ha->dmp_template);
!                         return (rval);
!                 }
!                 ddi_put32(ha->dmp_template.acc_handle, bp, fdata);
!                 bp++;
!         }
! 
!         QL_PRINT_10(ha, "done\n");
!         return (rval);
! }
! 
! static uint32_t
! ql_2700_dmp_parse_template(ql_adapter_state_t *ha, ql_dt_hdr_t *template_hdr,
!     uint8_t *dump_buff, uint32_t buff_size)
! {
!         int             e_cnt, esize, num_of_entries;
!         uint32_t        bsize;
!         time_t          time;
!         uint8_t         *dbuff, *dbuff_end;
!         ql_dt_entry_t   *entry;
!         int             sane_end = 0;
! 
!         dbuff = dump_buff;      /* dbuff = NULL size determination. */
!         dbuff_end = dump_buff + buff_size;
! 
!         template_hdr->ver_attr[0] = ha->fw_major_version;
!         template_hdr->ver_attr[1] = ha->fw_minor_version;
!         template_hdr->ver_attr[2] = ha->fw_subminor_version;
!         template_hdr->ver_attr[3] = ha->fw_attributes;
!         template_hdr->ver_attr[4] = ha->fw_ext_attributes;
! 
!         QL_PRINT_7(ha, "started, template_hdr=%ph, dump_buff=%ph, "
!             "buff_size=%xh, buff_end=%ph\n", (void *)template_hdr,
!             (void *)dbuff, buff_size, (void *)dbuff_end);
! 
!         /* Setup parameters */
!         QL_PRINT_7(ha, "type=%d, first_entry_offset=%xh, "
!             "num_of_entries=%xh ver_attr=%xh,%xh,%xh,%xh,%xh\n",
!             template_hdr->type, template_hdr->first_entry_offset,
!             template_hdr->num_of_entries, template_hdr->ver_attr[0],
!             template_hdr->ver_attr[1], template_hdr->ver_attr[2],
!             template_hdr->ver_attr[3], template_hdr->ver_attr[4]);
! 
!         if (template_hdr->type != DT_THDR) {
!                 EL(ha, "Template header not found\n");
!                 return (0);
!         }
!         if (dbuff != NULL) {
!                 (void) drv_getparm(TIME, &time);
!                 template_hdr->driver_timestamp = LSD(time);
!         }
! 
!         num_of_entries = template_hdr->num_of_entries;
!         entry = (ql_dt_entry_t *)((caddr_t)template_hdr +
!             template_hdr->first_entry_offset);
! 
!         bsize = template_hdr->size_of_template;
!         for (e_cnt = 0; e_cnt < num_of_entries; e_cnt++) {
!                 QL_PRINT_7(ha, "e_cnt=%xh, entry=%ph, type=%d, size=%xh, "
!                     "capture_flags=%xh, driver_flags=%xh, bofst=%xh\n",
!                     e_cnt, (void *)entry, entry->h.type, entry->h.size,
!                     entry->h.capture_flags, entry->h.driver_flags,
!                     dbuff != NULL ? (uintptr_t)dbuff - (uintptr_t)template_hdr :
!                     bsize);
!                 /*
!                  * Decode the entry type and process it accordingly
!                  */
!                 esize = 0;
!                 switch (entry->h.type) {
!                 case DT_NOP:
!                         if (dbuff != NULL) {
!                                 entry->h.driver_flags = (uint8_t)
!                                     (entry->h.driver_flags | SKIPPED_FLAG);
!                         }
!                         QL_PRINT_3(ha, "Skipping Entry ID=%d, type=%d\n",
!                             e_cnt, entry->h.type);
                          break;
+                 case DT_TEND:
+                         if (dbuff != NULL) {
+                                 entry->h.driver_flags = (uint8_t)
+                                     (entry->h.driver_flags | SKIPPED_FLAG);
+                         }
+                         QL_PRINT_3(ha, "Skipping Entry ID=%d, type=%d\n",
+                             e_cnt, entry->h.type);
+                         sane_end++;
+                         break;
+                 case DT_RIOB1:
+                         esize = ql_2700_dt_riob1(ha, (ql_dt_riob1_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_WIOB1:
+                         ql_2700_dt_wiob1(ha, (ql_dt_wiob1_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_RIOB2:
+                         esize = ql_2700_dt_riob2(ha, (ql_dt_riob2_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_WIOB2:
+                         ql_2700_dt_wiob2(ha, (ql_dt_wiob2_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_RPCI:
+                         esize = ql_2700_dt_rpci(ha, (ql_dt_rpci_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_WPCI:
+                         ql_2700_dt_wpci(ha, (ql_dt_wpci_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_RRAM:
+                         esize = ql_2700_dt_rram(ha, (ql_dt_rram_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_GQUE:
+                         esize = ql_2700_dt_gque(ha, (ql_dt_gque_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_GFCE:
+                         esize = ql_2700_dt_gfce(ha, (ql_dt_gfce_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_PRISC:
+                         ql_2700_dt_prisc(ha, (ql_dt_prisc_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_RRISC:
+                         ql_2700_dt_rrisc(ha, (ql_dt_rrisc_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_DINT:
+                         ql_2700_dt_dint(ha, (ql_dt_dint_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_GHBD:
+                         esize = ql_2700_dt_ghbd(ha, (ql_dt_ghbd_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_SCRA:
+                         esize = ql_2700_dt_scra(ha, (ql_dt_scra_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_RRREG:
+                         esize = ql_2700_dt_rrreg(ha, (ql_dt_rrreg_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_WRREG:
+                         ql_2700_dt_wrreg(ha, (ql_dt_wrreg_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_RRRAM:
+                         esize = ql_2700_dt_rrram(ha, (ql_dt_rrram_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_RPCIC:
+                         esize = ql_2700_dt_rpcic(ha, (ql_dt_rpcic_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_GQUES:
+                         esize = ql_2700_dt_gques(ha, (ql_dt_gques_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
+                 case DT_WDMP:
+                         esize = ql_2700_dt_wdmp(ha, (ql_dt_wdmp_t *)entry,
+                             dbuff, dbuff_end);
+                         break;
                  default:
!                         entry->h.driver_flags = (uint8_t)
!                             (entry->h.driver_flags | SKIPPED_FLAG);
!                         EL(ha, "Entry ID=%d, type=%d unknown\n", e_cnt,
!                             entry->h.type);
!                         break;
!                 }
!                 if (dbuff != NULL && esize) {
!                         QL_PRINT_7(ha, "entry=%d, esize=%xh, capture data\n",
!                             entry->h.type, esize);
!                         QL_DUMP_3(dbuff, 8, esize);
!                         dbuff += esize;
!                 }
!                 bsize += esize;
!                 /* next entry in the template */
!                 entry = (ql_dt_entry_t *)((caddr_t)entry + entry->h.size);
!         }
!         if (sane_end > 1) {
!                 EL(ha, "Template configuration error. Check Template\n");
!         }
! 
!         QL_PRINT_7(ha, "done, num of entries=%xh, size=%xh\n",
!             template_hdr->num_of_entries, bsize);
!         return (bsize);
! }
! 
! static int
! ql_2700_dt_riob1(ql_adapter_state_t *ha, ql_dt_riob1_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         int             esize;
!         uint32_t        i, cnt;
!         uint8_t         *bp = dbuff;
!         uint32_t        addr = entry->addr;
!         uint8_t         *reg = (uint8_t *)ha->iobase + entry->pci_offset;
! 
!         QL_PRINT_7(ha, "started, buf=%ph, addr=%xh, reg_size=%xh, "
!             "reg_count=%x%02xh, pci_offset=%xh\n", (void *)dbuff, entry->addr,
!             entry->reg_size, entry->reg_count_h, entry->reg_count_l,
!             entry->pci_offset);
! 
!         cnt = CHAR_TO_SHORT(entry->reg_count_l, entry->reg_count_h);
!         esize = cnt * 4;                /* addr */
!         esize += cnt * entry->reg_size; /* data */
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
!                 return (esize);
!         }
!         if (esize + dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return (0);
!         }
! 
!         WRT32_IO_REG(ha, io_base_addr, addr);
!         while (cnt--) {
!                 *bp++ = LSB(LSW(addr));
!                 *bp++ = MSB(LSW(addr));
!                 *bp++ = LSB(MSW(addr));
!                 *bp++ = MSB(MSW(addr));
!                 for (i = 0; i < entry->reg_size; i++) {
!                         *bp++ = RD_REG_BYTE(ha, reg++);
!                 }
!                 addr++;
!         }
! 
!         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
!         return (esize);
! }
! 
! static void
! ql_2700_dt_wiob1(ql_adapter_state_t *ha, ql_dt_wiob1_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         uint8_t *reg = (uint8_t *)ha->iobase + entry->pci_offset;
! 
!         QL_PRINT_7(ha, "started, addr=%xh, data=%xh, pci_offset=%xh\n",
!             entry->addr, entry->data, entry->pci_offset);
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done\n");
!                 return;
!         }
!         if (dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=0\n");
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return;
!         }
! 
!         WRT32_IO_REG(ha, io_base_addr, entry->addr);
!         WRT_REG_DWORD(ha, reg, entry->data);
! 
!         QL_PRINT_7(ha, "done\n");
! }
! 
! static int
! ql_2700_dt_riob2(ql_adapter_state_t *ha, ql_dt_riob2_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         int             esize;
!         uint32_t        i, cnt;
!         uint8_t         *bp = dbuff;
!         uint8_t         *reg = (uint8_t *)ha->iobase + entry->pci_offset;
!         uint32_t        addr = entry->addr;
! 
!         QL_PRINT_7(ha, "started, buf=%ph, addr=%xh, reg_size=%xh, "
!             "reg_count=%x%02xh, pci_offset=%xh, bank_sel_offset=%xh, "
!             "reg_bank=%xh\n", (void *)dbuff, entry->addr,
!             entry->reg_size, entry->reg_count_h, entry->reg_count_l,
!             entry->pci_offset, entry->bank_sel_offset, entry->reg_bank);
! 
!         cnt = CHAR_TO_SHORT(entry->reg_count_l, entry->reg_count_h);
!         esize = cnt * 4;                /* addr */
!         esize += cnt * entry->reg_size; /* data */
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
!                 return (esize);
!         }
!         if (esize + dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return (0);
!         }
! 
!         WRT32_IO_REG(ha, io_base_addr, addr);
!         WRT_REG_DWORD(ha, ha->iobase + entry->bank_sel_offset, entry->reg_bank);
!         while (cnt--) {
!                 *bp++ = LSB(LSW(addr));
!                 *bp++ = MSB(LSW(addr));
!                 *bp++ = LSB(MSW(addr));
!                 *bp++ = MSB(MSW(addr));
!                 for (i = 0; i < entry->reg_size; i++) {
!                         *bp++ = RD_REG_BYTE(ha, reg++);
!                 }
!                 addr++;
!         }
! 
!         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
!         return (esize);
! }
! 
! static void
! ql_2700_dt_wiob2(ql_adapter_state_t *ha, ql_dt_wiob2_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         uint16_t        data;
!         uint8_t         *reg = (uint8_t *)ha->iobase + entry->pci_offset;
! 
!         QL_PRINT_7(ha, "started, addr=%xh, data=%x%02xh, pci_offset=%xhh, "
!             "bank_sel_offset=%xh, reg_bank=%xh\n", entry->addr, entry->data_h,
!             entry->data_l, entry->pci_offset, entry->bank_sel_offset,
!             entry->reg_bank);
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done\n");
!                 return;
!         }
!         if (dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=0\n");
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return;
!         }
! 
!         data = CHAR_TO_SHORT(entry->data_l, entry->data_h);
! 
!         WRT32_IO_REG(ha, io_base_addr, entry->addr);
!         WRT_REG_DWORD(ha, ha->iobase + entry->bank_sel_offset, entry->reg_bank);
!         WRT_REG_WORD(ha, reg, data);
! 
!         QL_PRINT_7(ha, "done\n");
! }
! 
! static int
! ql_2700_dt_rpci(ql_adapter_state_t *ha, ql_dt_rpci_t *entry, uint8_t *dbuff,
!     uint8_t *dbuff_end)
! {
!         int             esize;
!         uint32_t        i;
!         uint8_t         *bp = dbuff;
!         uint8_t         *reg = (uint8_t *)ha->iobase + entry->addr;
! 
!         QL_PRINT_7(ha, "started, addr=%xh, reg=%ph\n", entry->addr,
!             (void *)reg);
! 
!         esize = 4;      /* addr */
!         esize += 4;     /* data */
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
!                 return (esize);
!         }
!         if (esize + dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return (0);
!         }
! 
!         *bp++ = LSB(LSW(entry->addr));
!         *bp++ = MSB(LSW(entry->addr));
!         *bp++ = LSB(MSW(entry->addr));
!         *bp++ = MSB(MSW(entry->addr));
!         for (i = 0; i < 4; i++) {
!                 *bp++ = RD_REG_BYTE(ha, reg++);
!         }
! 
!         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
!         return (esize);
! }
! 
! static void
! ql_2700_dt_wpci(ql_adapter_state_t *ha, ql_dt_wpci_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         uint8_t *reg = (uint8_t *)ha->iobase + entry->addr;
! 
!         QL_PRINT_7(ha, "started, addr=%xh, data=%xh, reg=%ph\n",
!             entry->addr, entry->data, (void *)reg);
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done\n");
!                 return;
!         }
!         if (dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=0\n");
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return;
!         }
! 
!         WRT_REG_DWORD(ha, reg, entry->data);
! 
!         QL_PRINT_7(ha, "done\n");
! }
! 
! static int
! ql_2700_dt_rram(ql_adapter_state_t *ha, ql_dt_rram_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         int             esize, rval;
!         uint32_t        start = entry->start_addr;
!         uint32_t        end = entry->end_addr;
! 
!         QL_PRINT_7(ha, "started, buf=%ph, ram_area=%xh, start_addr=%xh, "
!             "end_addr=%xh\n", (void *)dbuff, entry->ram_area,
!             entry->start_addr, entry->end_addr);
! 
!         if (entry->ram_area == 2) {
!                 end = ha->fw_ext_memory_end;
!         } else if (entry->ram_area == 3) {
!                 start = ha->fw_shared_ram_start;
!                 end = ha->fw_shared_ram_end;
!         } else if (entry->ram_area == 4) {
!                 start = ha->fw_ddr_ram_start;
!                 end = ha->fw_ddr_ram_end;
!         } else if (entry->ram_area != 1) {
!                 EL(ha, "skipped, unknown RAM_AREA %d\n", entry->ram_area);
!                 start = 0;
!                 end = 0;
!         }
!         esize = end > start ? end - start : 0;
!         if (esize) {
!                 esize = (esize + 1) * 4;
!         }
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
!                 return (esize);
!         }
!         if (esize == 0 || esize + dbuff >= dbuff_end) {
!                 if (esize != 0) {
!                         EL(ha, "skipped, no buffer space, needed=%xh\n",
!                             esize);
!                 } else {
!                         /*EMPTY*/
!                         QL_PRINT_7(ha, "skipped, no ram_area=%xh, start=%xh, "
!                             "end=%xh\n", entry->ram_area, start, end);
!                 }
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return (0);
!         }
!         entry->end_addr = end;
!         entry->start_addr = start;
! 
!         if ((rval = ql_2700_dump_ram(ha, MBC_DUMP_RAM_EXTENDED,
!             start, esize / 4, dbuff)) != QL_SUCCESS) {
!                 EL(ha, "dump_ram failed, rval=%xh, addr=%xh, len=%xh, "
!                     "esize=0\n", rval, start, esize / 4);
!                 return (0);
!         }
! 
!         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
!         return (esize);
! }
! 
! static int
! ql_2700_dt_gque(ql_adapter_state_t *ha, ql_dt_gque_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         int             esize;
!         uint32_t        cnt, q_cnt, e_cnt, i;
!         uint8_t         *bp = dbuff, *dp;
! 
!         QL_PRINT_7(ha, "started, buf=%ph, num_queues=%xh, queue_type=%xh\n",
!             (void *)dbuff, entry->num_queues, entry->queue_type);
! 
!         if (entry->queue_type == 1) {
!                 ql_request_q_t  *req_q;
! 
!                 e_cnt = ha->rsp_queues_cnt > 1 ? 2 : 1;
!                 esize = e_cnt * 2;      /* queue number */
!                 esize += e_cnt * 2;     /* queue entries */
! 
!                 /* queue size */
!                 esize += ha->req_q[0]->req_entry_cnt * REQUEST_ENTRY_SIZE;
!                 if (e_cnt > 1) {
!                         esize += ha->req_q[1]->req_entry_cnt *
!                             REQUEST_ENTRY_SIZE;
!                 }
! 
!                 if (dbuff == NULL) {
!                         QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
!                         return (esize);
!                 }
!                 if (esize + dbuff >= dbuff_end) {
!                         EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
!                         entry->h.driver_flags = (uint8_t)
!                             (entry->h.driver_flags | SKIPPED_FLAG);
!                         return (0);
!                 }
!                 entry->num_queues = e_cnt;
! 
!                 for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
!                         req_q = q_cnt == 0 ? ha->req_q[0] : ha->req_q[1];
!                         e_cnt = req_q->req_entry_cnt;
!                         dp = req_q->req_ring.bp;
!                         *bp++ = LSB(q_cnt);
!                         *bp++ = MSB(q_cnt);
!                         *bp++ = LSB(e_cnt);
!                         *bp++ = MSB(e_cnt);
!                         for (cnt = 0; cnt < e_cnt; cnt++) {
!                                 for (i = 0; i < REQUEST_ENTRY_SIZE; i++) {
!                                         *bp++ = *dp++;
!                                 }
!                         }
!                 }
!         } else if (entry->queue_type == 2) {
!                 ql_response_q_t *rsp_q;
! 
!                 e_cnt = ha->rsp_queues_cnt;
!                 esize = e_cnt * 2;      /* queue number */
!                 esize += e_cnt * 2;     /* queue entries */
! 
!                 /* queue size */
!                 for (q_cnt = 0; q_cnt < ha->rsp_queues_cnt; q_cnt++) {
!                         rsp_q = ha->rsp_queues[q_cnt];
!                         esize += rsp_q->rsp_entry_cnt * RESPONSE_ENTRY_SIZE;
!                 }
! 
!                 if (dbuff == NULL) {
!                         QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
!                         return (esize);
!                 }
!                 if (esize + dbuff >= dbuff_end) {
!                         EL(ha, "skipped2, no buffer space, needed=%xh\n",
!                             esize);
!                         entry->h.driver_flags = (uint8_t)
!                             (entry->h.driver_flags | SKIPPED_FLAG);
!                         return (0);
!                 }
!                 entry->num_queues = e_cnt;
! 
!                 for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
!                         rsp_q = ha->rsp_queues[q_cnt];
!                         e_cnt = rsp_q->rsp_entry_cnt;
!                         dp = rsp_q->rsp_ring.bp;
!                         *bp++ = LSB(q_cnt);
!                         *bp++ = MSB(q_cnt);
!                         *bp++ = LSB(e_cnt);
!                         *bp++ = MSB(e_cnt);
!                         for (cnt = 0; cnt < e_cnt; cnt++) {
!                                 for (i = 0; i < RESPONSE_ENTRY_SIZE; i++) {
!                                         *bp++ = *dp++;
!                                 }
!                         }
!                 }
!         } else if (entry->queue_type == 3) {
!                 QL_PRINT_7(ha, "skipped, no ATIO queue, esize=0\n");
!                 if (dbuff != NULL) {
!                         entry->num_queues = 0;
!                         entry->h.driver_flags = (uint8_t)
!                             (entry->h.driver_flags | SKIPPED_FLAG);
!                 }
!                 return (0);
!         } else {
!                 EL(ha, "skipped, unknown queue_type %d, esize=0\n",
!                     entry->queue_type);
!                 if (dbuff != NULL) {
!                         entry->h.driver_flags = (uint8_t)
!                             (entry->h.driver_flags | SKIPPED_FLAG);
!                 }
!                 return (0);
!         }
! 
!         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
!         return (esize);
! }
! 
! /*ARGSUSED*/
! static int
! ql_2700_dt_gfce(ql_adapter_state_t *ha, ql_dt_gfce_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         QL_PRINT_7(ha, "started\n");
! 
!         QL_PRINT_7(ha, "skipped, not supported, esize=0\n");
!         if (dbuff != NULL) {
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!         }
! 
!         return (0);
! }
! 
! static void
! ql_2700_dt_prisc(ql_adapter_state_t *ha, ql_dt_prisc_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         clock_t timer;
! 
!         QL_PRINT_7(ha, "started\n");
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done\n");
!                 return;
!         }
!         if (dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=0\n");
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return;
!         }
! 
!         /* Pause RISC. */
!         if ((RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0) {
!                 WRT32_IO_REG(ha, hccr, HC24_PAUSE_RISC);
!                 for (timer = 30000;
!                     (RD32_IO_REG(ha, risc2host) & RH_RISC_PAUSED) == 0;
!                     timer--) {
!                         if (timer) {
!                                 drv_usecwait(100);
!                                 if (timer % 10000 == 0) {
!                                         EL(ha, "risc pause %d\n", timer);
!                                 }
!                         } else {
!                                 EL(ha, "risc pause timeout\n");
!                                 break;
!                         }
!                 }
!         }
! 
!         QL_PRINT_7(ha, "done\n");
! }
! 
! static void
! ql_2700_dt_rrisc(ql_adapter_state_t *ha, ql_dt_rrisc_t *entry,
!     uint8_t *dbuff, uint8_t *dbuff_end)
! {
!         clock_t timer;
! 
!         QL_PRINT_7(ha, "started\n");
! 
!         if (dbuff == NULL) {
!                 QL_PRINT_7(ha, "null buf done\n");
!                 return;
!         }
!         if (dbuff >= dbuff_end) {
!                 EL(ha, "skipped, no buffer space, needed=0\n");
!                 entry->h.driver_flags = (uint8_t)
!                     (entry->h.driver_flags | SKIPPED_FLAG);
!                 return;
!         }
! 
!         /* Shutdown DMA. */
!         WRT32_IO_REG(ha, ctrl_status, DMA_SHUTDOWN);
! 
!         /* Wait for DMA to stop. */
!         for (timer = 0; timer < 30000; timer++) {
!                 if (!(RD32_IO_REG(ha, ctrl_status) & DMA_ACTIVE)) {
!                         break;
!                 }
!                 drv_usecwait(100);
!         }
! 
!         /* Reset the chip. */
!         WRT32_IO_REG(ha, ctrl_status, ISP_RESET);
!         drv_usecwait(200);
! 
!         /* Wait for RISC to recover from reset. */
!         for (timer = 30000; timer; timer--) {
!                 ha->rom_status = RD16_IO_REG(ha, mailbox_out[0]);
!                 if ((ha->rom_status & MBS_ROM_STATUS_MASK) != MBS_ROM_BUSY) {
!                         break;
!                 }
!                 drv_usecwait(100);
!         }
! 
!         /* Wait for reset to finish. */
!         for (timer = 30000; timer; timer--) {
!                 if (!(RD32_IO_REG(ha, ctrl_status) & ISP_RESET)) {
!                         break;
!                 }
!                 drv_usecwait(100);
!         }
! 
!         ADAPTER_STATE_LOCK(ha);
!         ha->flags &= ~FIRMWARE_UP;
          ADAPTER_STATE_UNLOCK(ha);
+ 
+         QL_PRINT_7(ha, "done\n");
+ }
+ 
+ static void
+ ql_2700_dt_dint(ql_adapter_state_t *ha, ql_dt_dint_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         QL_PRINT_7(ha, "started, pci_offset=%xh, data=%xh\n",
+             entry->pci_offset, entry->data);
+ 
+         if (dbuff == NULL) {
+                 QL_PRINT_7(ha, "null buf done\n");
+                 return;
+         }
+         if (dbuff >= dbuff_end) {
+                 EL(ha, "skipped, no buffer space, needed=0\n");
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+                 return;
+         }
+ 
+         ql_pci_config_put32(ha, entry->pci_offset, entry->data);
+ 
+         QL_PRINT_7(ha, "done\n");
+ }
+ 
+ /*ARGSUSED*/
+ static int
+ ql_2700_dt_ghbd(ql_adapter_state_t *ha, ql_dt_ghbd_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         QL_PRINT_7(ha, "started\n");
+ 
+         QL_PRINT_7(ha, "skipped, not supported\n");
+         if (dbuff != NULL) {
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+         }
+ 
+         return (0);
+ }
+ 
+ /*ARGSUSED*/
+ static int
+ ql_2700_dt_scra(ql_adapter_state_t *ha, ql_dt_scra_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         QL_PRINT_7(ha, "started\n");
+ 
+         QL_PRINT_7(ha, "skipped, not supported, esize=0\n");
+         if (dbuff != NULL) {
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+         }
+ 
+         return (0);
+ }
+ 
+ static int
+ ql_2700_dt_rrreg(ql_adapter_state_t *ha, ql_dt_rrreg_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         int             esize;
+         uint32_t        i;
+         uint8_t         *bp = dbuff;
+         uint8_t         *reg = (uint8_t *)ha->iobase + 0xc4;
+         uint32_t        addr = entry->addr;
+         uint32_t        cnt = entry->count;
+ 
+         QL_PRINT_7(ha, "started, buf=%ph, addr=%xh, count=%xh\n",
+             (void *)dbuff, entry->addr, entry->count);
+ 
+         esize = cnt * 4;        /* addr */
+         esize += cnt * 4;       /* data */
+ 
+         if (dbuff == NULL) {
+                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
+                 return (esize);
+         }
+         if (esize + dbuff >= dbuff_end) {
+                 EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+                 return (0);
+         }
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x40);
+         while (cnt--) {
+                 WRT_REG_DWORD(ha, ha->iobase + 0xc0, addr | 0x80000000);
+                 *bp++ = LSB(LSW(addr));
+                 *bp++ = MSB(LSW(addr));
+                 *bp++ = LSB(MSW(addr));
+                 *bp++ = MSB(MSW(addr));
+                 for (i = 0; i < 4; i++) {
+                         *bp++ = RD_REG_BYTE(ha, reg + i);
+                 }
+                 addr += 4;
+         }
+ 
+         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
+         return (esize);
+ }
+ 
+ static void
+ ql_2700_dt_wrreg(ql_adapter_state_t *ha, ql_dt_wrreg_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         QL_PRINT_7(ha, "started, addr=%xh, data=%xh\n", entry->addr,
+             entry->data);
+ 
+         if (dbuff == NULL) {
+                 QL_PRINT_7(ha, "null buf done\n");
+                 return;
+         }
+         if (dbuff >= dbuff_end) {
+                 EL(ha, "skipped, no buffer space, needed=0\n");
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+                 return;
+         }
+ 
+         WRT32_IO_REG(ha, io_base_addr, 0x40);
+         WRT_REG_DWORD(ha, ha->iobase + 0xc4, entry->data);
+         WRT_REG_DWORD(ha, ha->iobase + 0xc0, entry->addr);
+ 
+         QL_PRINT_7(ha, "done\n");
+ }
+ 
+ static int
+ ql_2700_dt_rrram(ql_adapter_state_t *ha, ql_dt_rrram_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         int     rval, esize;
+ 
+         QL_PRINT_7(ha, "started, buf=%ph, addr=%xh, count=%xh\n",
+             (void *)dbuff, entry->addr, entry->count);
+ 
+         esize = entry->count * 4;       /* data */
+ 
+         if (dbuff == NULL) {
+                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
+                 return (esize);
+         }
+         if (esize + dbuff >= dbuff_end) {
+                 EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+                 return (0);
+         }
+ 
+         if ((rval = ql_2700_dump_ram(ha, MBC_MPI_RAM, entry->addr,
+             entry->count, dbuff)) != QL_SUCCESS) {
+                 EL(ha, "dump_ram failed, rval=%xh, addr=%xh, len=%xh, "
+                     "esize=0\n", rval, entry->addr, entry->count);
+                 return (0);
+         }
+ 
+         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
+         return (esize);
+ }
+ 
+ static int
+ ql_2700_dt_rpcic(ql_adapter_state_t *ha, ql_dt_rpcic_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         int             esize;
+         uint32_t        i;
+         uint8_t         *bp = dbuff;
+         uint32_t        addr = entry->addr;
+         uint32_t        cnt = entry->count;
+ 
+         QL_PRINT_7(ha, "started, buf=%ph, addr=%xh, count=%xh\n",
+             (void *)dbuff, entry->addr, entry->count);
+ 
+         esize = cnt * 4;        /* addr */
+         esize += cnt * 4;       /* data */
+ 
+         if (dbuff == NULL) {
+                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
+                 return (esize);
+         }
+         if (esize + dbuff >= dbuff_end) {
+                 EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+                 return (0);
+         }
+ 
+         while (cnt--) {
+                 *bp++ = LSB(LSW(addr));
+                 *bp++ = MSB(LSW(addr));
+                 *bp++ = LSB(MSW(addr));
+                 *bp++ = MSB(MSW(addr));
+                 for (i = 0; i < 4; i++) {
+                         *bp++ = ql_pci_config_get8(ha, addr++);
+                 }
+         }
+ 
+         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
+         return (esize);
+ }
+ 
+ static int
+ ql_2700_dt_gques(ql_adapter_state_t *ha, ql_dt_gques_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         int             esize;
+         uint32_t        q_cnt, e_cnt, data;
+         uint8_t         *bp = dbuff;
+ 
+         QL_PRINT_7(ha, "started, buf=%ph, num_queues=%xh, queue_type=%xh\n",
+             (void *)dbuff, entry->num_queues, entry->queue_type);
+ 
+         if (entry->queue_type == 1) {
+                 ql_request_q_t  *req_q;
+ 
+                 e_cnt = ha->rsp_queues_cnt > 1 ? 2 : 1;
+                 esize = e_cnt * 2;      /* queue number */
+                 esize += e_cnt * 2;     /* shadow entries */
+ 
+                 /* shadow size */
+                 esize += SHADOW_ENTRY_SIZE;
+                 if (e_cnt > 1) {
+                         esize += SHADOW_ENTRY_SIZE;
+                 }
+                 if (dbuff == NULL) {
+                         QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
+                         return (esize);
+                 }
+                 if (esize + dbuff >= dbuff_end) {
+                         EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
+                         entry->h.driver_flags = (uint8_t)
+                             (entry->h.driver_flags | SKIPPED_FLAG);
+                         return (0);
+                 }
+                 entry->num_queues = e_cnt;
+ 
+                 for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
+                         req_q = q_cnt == 0 ? ha->req_q[0] : ha->req_q[1];
+                         e_cnt = 1;
+                         data = ddi_get32(req_q->req_ring.acc_handle,
+                             req_q->req_out_shadow_ptr);
+                         *bp++ = LSB(q_cnt);
+                         *bp++ = MSB(q_cnt);
+                         *bp++ = LSB(e_cnt);
+                         *bp++ = MSB(e_cnt);
+                         *bp++ = LSB(LSW(data));
+                         *bp++ = MSB(LSW(data));
+                         *bp++ = LSB(MSW(data));
+                         *bp++ = MSB(MSW(data));
+                 }
+         } else if (entry->queue_type == 2) {
+                 ql_response_q_t *rsp_q;
+ 
+                 e_cnt = ha->rsp_queues_cnt;
+                 esize = e_cnt * 2;      /* queue number */
+                 esize += e_cnt * 2;     /* shadow entries */
+ 
+                 /* shadow size */
+                 for (q_cnt = 0; q_cnt < ha->rsp_queues_cnt; q_cnt++) {
+                         esize += SHADOW_ENTRY_SIZE;
+                 }
+ 
+                 if (dbuff == NULL) {
+                         QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
+                         return (esize);
+                 }
+                 if (esize + dbuff >= dbuff_end) {
+                         EL(ha, "skipped2, no buffer space, needed=%xh\n",
+                             esize);
+                         entry->h.driver_flags = (uint8_t)
+                             (entry->h.driver_flags | SKIPPED_FLAG);
+                         return (0);
+                 }
+                 entry->num_queues = e_cnt;
+ 
+                 for (q_cnt = 0; q_cnt < entry->num_queues; q_cnt++) {
+                         rsp_q = ha->rsp_queues[q_cnt];
+                         e_cnt = 1;
+                         data = ddi_get32(rsp_q->rsp_ring.acc_handle,
+                             rsp_q->rsp_in_shadow_ptr);
+                         *bp++ = LSB(q_cnt);
+                         *bp++ = MSB(q_cnt);
+                         *bp++ = LSB(e_cnt);
+                         *bp++ = MSB(e_cnt);
+                         *bp++ = LSB(LSW(data));
+                         *bp++ = MSB(LSW(data));
+                         *bp++ = LSB(MSW(data));
+                         *bp++ = MSB(MSW(data));
+                 }
+         } else if (entry->queue_type == 3) {
+                 EL(ha, "skipped, no ATIO queue, esize=0\n");
+                 if (dbuff != NULL) {
+                         entry->num_queues = 0;
+                         entry->h.driver_flags = (uint8_t)
+                             (entry->h.driver_flags | SKIPPED_FLAG);
+                 }
+                 return (0);
+         } else {
+                 EL(ha, "skipped, unknown queue_type %d, esize=0\n",
+                     entry->queue_type);
+                 if (dbuff != NULL) {
+                         entry->h.driver_flags = (uint8_t)
+                             (entry->h.driver_flags | SKIPPED_FLAG);
+                 }
+                 return (0);
+         }
+ 
+         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
+         return (esize);
+ }
+ 
+ static int
+ ql_2700_dt_wdmp(ql_adapter_state_t *ha, ql_dt_wdmp_t *entry,
+     uint8_t *dbuff, uint8_t *dbuff_end)
+ {
+         int             esize;
+         uint8_t         *bp = dbuff;
+         uint32_t        data, cnt = entry->length, *dp = entry->data;
+ 
+         QL_PRINT_7(ha, "started, buf=%ph, length=%xh\n",
+             (void *)dbuff, entry->length);
+ 
+         esize = cnt;
+         if (dbuff == NULL) {
+                 QL_PRINT_7(ha, "null buf done, esize=%xh\n", esize);
+                 return (esize);
+         }
+         if (esize + dbuff >= dbuff_end) {
+                 EL(ha, "skipped, no buffer space, needed=%xh\n", esize);
+                 entry->h.driver_flags = (uint8_t)
+                     (entry->h.driver_flags | SKIPPED_FLAG);
+                 return (0);
+         }
+ 
+         while (cnt--) {
+                 data = *dp++;
+                 *bp++ = LSB(LSW(data));
+                 *bp++ = MSB(LSW(data));
+                 *bp++ = LSB(MSW(data));
+                 *bp++ = MSB(MSW(data));
+         }
+         QL_PRINT_7(ha, "%s\n", dbuff);
+ 
+         QL_PRINT_7(ha, "done, esize=%xh\n", esize);
+         return (esize);
+ }
+ 
+ /*
+  * ql_2700_dump_ram
+  *      Dumps RAM.
+  *      Risc interrupts must be disabled when this routine is called.
+  *
+  * Input:
+  *      ha:             adapter state pointer.
+  *      cmd:            MBC_DUMP_RAM_EXTENDED/MBC_MPI_RAM.
+  *      risc_address:   RISC code start address.
+  *      len:            Number of words.
+  *      bp:             buffer pointer.
+  *
+  * Returns:
+  *      ql local function return status code.
+  *
+  * Context:
+  *      Interrupt or Kernel context, no mailbox commands allowed.
+  */
+ static int
+ ql_2700_dump_ram(ql_adapter_state_t *ha, uint16_t cmd, uint32_t risc_address,
+     uint32_t len, uint8_t *bp)
+ {
+         dma_mem_t       mem;
+         uint32_t        i, stat, timer;
+         uint8_t         *dp;
+         int             rval = QL_SUCCESS;
+ 
+         QL_PRINT_7(ha, "started, cmd=%xh, risc_address=%xh, len=%xh, "
+             "bp=%ph\n", cmd, risc_address, len, (void *)bp);
+ 
+         mem.size = len * 4;
+         mem.type = LITTLE_ENDIAN_DMA;
+         mem.max_cookie_count = 1;
+         mem.alignment = 8;
+         if ((rval = ql_alloc_phys(ha, &mem, KM_SLEEP)) != QL_SUCCESS) {
+                 EL(ha, "alloc status=%xh\n", rval);
+                 return (rval);
+         }
+ 
+         WRT16_IO_REG(ha, mailbox_in[0], cmd);
+         WRT16_IO_REG(ha, mailbox_in[1], LSW(risc_address));
+         WRT16_IO_REG(ha, mailbox_in[2], MSW(LSD(mem.cookie.dmac_laddress)));
+         WRT16_IO_REG(ha, mailbox_in[3], LSW(LSD(mem.cookie.dmac_laddress)));
+         WRT16_IO_REG(ha, mailbox_in[4], MSW(len));
+         WRT16_IO_REG(ha, mailbox_in[5], LSW(len));
+         WRT16_IO_REG(ha, mailbox_in[6], MSW(MSD(mem.cookie.dmac_laddress)));
+         WRT16_IO_REG(ha, mailbox_in[7], LSW(MSD(mem.cookie.dmac_laddress)));
+         WRT16_IO_REG(ha, mailbox_in[8], MSW(risc_address));
+         if (cmd == MBC_MPI_RAM) {
+                 WRT16_IO_REG(ha, mailbox_in[9], BIT_0);
+         }
+ 
+         WRT32_IO_REG(ha, hccr, HC24_SET_HOST_INT);
+         for (timer = 6000000; timer && rval == QL_SUCCESS; timer--) {
+                 stat = RD32_IO_REG(ha, risc2host);
+                 if (stat & RH_RISC_INT) {
+                         stat &= 0xff;
+                         if ((stat == 1) || (stat == 0x10)) {
                                  break;
+                         } else if ((stat == 2) || (stat == 0x11)) {
+                                 rval = RD16_IO_REG(ha, mailbox_out[0]);
+                                 break;
                          }
+                         WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
+                 }
+                 drv_usecwait(5);
+         }
+         WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT);
+ 
+         if (timer == 0) {
+                 QL_PRINT_7(ha, "timeout addr=%xh\n", risc_address);
+                 rval = QL_FUNCTION_TIMEOUT;
+         } else {
+                 (void) ddi_dma_sync(mem.dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
+                 dp = mem.bp;
+                 for (i = 0; i < mem.size; i++) {
+                         *bp++ = *dp++;
+                 }
+         }
+ 
+         ql_free_phys(ha, &mem);
+ 
+         QL_PRINT_7(ha, "done\n");
+         return (rval);
  }