1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  26  * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
  27  * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
  28  */
  29 
  30 /*
  31  * Copyright (c) 2000 to 2010, LSI Corporation.
  32  * All rights reserved.
  33  *
  34  * Redistribution and use in source and binary forms of all code within
  35  * this file that is exclusively owned by LSI, with or without
  36  * modification, is permitted provided that, in addition to the CDDL 1.0
  37  * License requirements, the following conditions are met:
  38  *
  39  *    Neither the name of the author nor the names of its contributors may be
  40  *    used to endorse or promote products derived from this software without
  41  *    specific prior written permission.
  42  *
  43  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  44  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  46  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  47  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  48  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  49  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  50  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  51  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  52  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  53  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  54  * DAMAGE.
  55  */
  56 
  57 /*
  58  * mptsas - This is a driver based on LSI Logic's MPT2.0/2.5 interface.
  59  *
  60  */
  61 
  62 #if defined(lint) || defined(DEBUG)
  63 #define MPTSAS_DEBUG
  64 #endif
  65 
  66 /*
  67  * standard header files.
  68  */
  69 #include <sys/note.h>
  70 #include <sys/scsi/scsi.h>
  71 #include <sys/pci.h>
  72 #include <sys/file.h>
  73 #include <sys/policy.h>
  74 #include <sys/model.h>
  75 #include <sys/sysevent.h>
  76 #include <sys/sysevent/eventdefs.h>
  77 #include <sys/sysevent/dr.h>
  78 #include <sys/sata/sata_defs.h>
  79 #include <sys/scsi/generic/sas.h>
  80 #include <sys/scsi/impl/scsi_sas.h>
  81 
  82 #pragma pack(1)
  83 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h>
  84 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h>
  85 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_cnfg.h>
  86 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h>
  87 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_ioc.h>
  88 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_sas.h>
  89 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_tool.h>
  90 #include <sys/scsi/adapters/mpt_sas/mpi/mpi2_raid.h>
  91 #pragma pack()
  92 
  93 /*
  94  * private header files.
  95  *
  96  */
  97 #include <sys/scsi/impl/scsi_reset_notify.h>
  98 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
  99 #include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h>
 100 #include <sys/scsi/adapters/mpt_sas/mptsas_smhba.h>
 101 #include <sys/scsi/adapters/mpt_sas/mptsas_hash.h>
 102 #include <sys/raidioctl.h>
 103 
 104 #include <sys/fs/dv_node.h>       /* devfs_clean */
 105 
 106 /*
 107  * FMA header files
 108  */
 109 #include <sys/ddifm.h>
 110 #include <sys/fm/protocol.h>
 111 #include <sys/fm/util.h>
 112 #include <sys/fm/io/ddi.h>
 113 
 114 /*
 115  * autoconfiguration data and routines.
 116  */
 117 static int mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 118 static int mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 119 static int mptsas_power(dev_info_t *dip, int component, int level);
 120 
 121 /*
 122  * cb_ops function
 123  */
 124 static int mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 125         cred_t *credp, int *rval);
 126 #ifdef __sparc
 127 static int mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd);
 128 #else  /* __sparc */
 129 static int mptsas_quiesce(dev_info_t *devi);
 130 #endif  /* __sparc */
 131 
 132 /*
 133  * Resource initilaization for hardware
 134  */
 135 static void mptsas_setup_cmd_reg(mptsas_t *mpt);
 136 static void mptsas_disable_bus_master(mptsas_t *mpt);
 137 static void mptsas_hba_fini(mptsas_t *mpt);
 138 static void mptsas_cfg_fini(mptsas_t *mptsas_blkp);
 139 static int mptsas_hba_setup(mptsas_t *mpt);
 140 static void mptsas_hba_teardown(mptsas_t *mpt);
 141 static int mptsas_config_space_init(mptsas_t *mpt);
 142 static void mptsas_config_space_fini(mptsas_t *mpt);
 143 static void mptsas_iport_register(mptsas_t *mpt);
 144 static int mptsas_smp_setup(mptsas_t *mpt);
 145 static void mptsas_smp_teardown(mptsas_t *mpt);
 146 static int mptsas_cache_create(mptsas_t *mpt);
 147 static void mptsas_cache_destroy(mptsas_t *mpt);
 148 static int mptsas_alloc_request_frames(mptsas_t *mpt);
 149 static int mptsas_alloc_reply_frames(mptsas_t *mpt);
 150 static int mptsas_alloc_free_queue(mptsas_t *mpt);
 151 static int mptsas_alloc_post_queue(mptsas_t *mpt);
 152 static void mptsas_alloc_reply_args(mptsas_t *mpt);
 153 static int mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 154 static void mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd);
 155 static int mptsas_init_chip(mptsas_t *mpt, int first_time);
 156 
 157 /*
 158  * SCSA function prototypes
 159  */
 160 static int mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 161 static int mptsas_scsi_reset(struct scsi_address *ap, int level);
 162 static int mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 163 static int mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly);
 164 static int mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 165     int tgtonly);
 166 static void mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
 167 static struct scsi_pkt *mptsas_scsi_init_pkt(struct scsi_address *ap,
 168     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
 169         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 170 static void mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
 171 static void mptsas_scsi_destroy_pkt(struct scsi_address *ap,
 172     struct scsi_pkt *pkt);
 173 static int mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 174     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 175 static void mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 176     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 177 static int mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
 178     void (*callback)(caddr_t), caddr_t arg);
 179 static int mptsas_get_name(struct scsi_device *sd, char *name, int len);
 180 static int mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len);
 181 static int mptsas_scsi_quiesce(dev_info_t *dip);
 182 static int mptsas_scsi_unquiesce(dev_info_t *dip);
 183 static int mptsas_bus_config(dev_info_t *pdip, uint_t flags,
 184     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 185 
 186 /*
 187  * SMP functions
 188  */
 189 static int mptsas_smp_start(struct smp_pkt *smp_pkt);
 190 
 191 /*
 192  * internal function prototypes.
 193  */
 194 static void mptsas_list_add(mptsas_t *mpt);
 195 static void mptsas_list_del(mptsas_t *mpt);
 196 
 197 static int mptsas_quiesce_bus(mptsas_t *mpt);
 198 static int mptsas_unquiesce_bus(mptsas_t *mpt);
 199 
 200 static int mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size);
 201 static void mptsas_free_handshake_msg(mptsas_t *mpt);
 202 
 203 static void mptsas_ncmds_checkdrain(void *arg);
 204 
 205 static int mptsas_prepare_pkt(mptsas_cmd_t *cmd);
 206 static int mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 207 static int mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *sp);
 208 static void mptsas_accept_tx_waitq(mptsas_t *mpt);
 209 
 210 static int mptsas_do_detach(dev_info_t *dev);
 211 static int mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl);
 212 static int mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun,
 213     struct scsi_pkt *pkt);
 214 static int mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp);
 215 
 216 static void mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd);
 217 static void mptsas_handle_event(void *args);
 218 static int mptsas_handle_event_sync(void *args);
 219 static void mptsas_handle_dr(void *args);
 220 static void mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
 221     dev_info_t *pdip);
 222 
 223 static void mptsas_restart_cmd(void *);
 224 
 225 static void mptsas_flush_hba(mptsas_t *mpt);
 226 static void mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun,
 227         uint8_t tasktype);
 228 static void mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd,
 229     uchar_t reason, uint_t stat);
 230 
 231 static uint_t mptsas_intr(caddr_t arg1, caddr_t arg2);
 232 static void mptsas_process_intr(mptsas_t *mpt,
 233     pMpi2ReplyDescriptorsUnion_t reply_desc_union);
 234 static void mptsas_handle_scsi_io_success(mptsas_t *mpt,
 235     pMpi2ReplyDescriptorsUnion_t reply_desc);
 236 static void mptsas_handle_address_reply(mptsas_t *mpt,
 237     pMpi2ReplyDescriptorsUnion_t reply_desc);
 238 static int mptsas_wait_intr(mptsas_t *mpt, int polltime);
 239 static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
 240     uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 241 
 242 static void mptsas_watch(void *arg);
 243 static void mptsas_watchsubr(mptsas_t *mpt);
 244 static void mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt);
 245 
 246 static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 247 static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
 248     uint8_t *data, uint32_t request_size, uint32_t reply_size,
 249     uint32_t data_size, uint32_t direction, uint8_t *dataout,
 250     uint32_t dataout_size, short timeout, int mode);
 251 static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 252 
 253 static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
 254     uint32_t unique_id);
 255 static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
 256 static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
 257     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
 258 static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
 259     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
 260     uint32_t diag_type);
 261 static int mptsas_diag_register(mptsas_t *mpt,
 262     mptsas_fw_diag_register_t *diag_register, uint32_t *return_code);
 263 static int mptsas_diag_unregister(mptsas_t *mpt,
 264     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code);
 265 static int mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
 266     uint32_t *return_code);
 267 static int mptsas_diag_read_buffer(mptsas_t *mpt,
 268     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
 269     uint32_t *return_code, int ioctl_mode);
 270 static int mptsas_diag_release(mptsas_t *mpt,
 271     mptsas_fw_diag_release_t *diag_release, uint32_t *return_code);
 272 static int mptsas_do_diag_action(mptsas_t *mpt, uint32_t action,
 273     uint8_t *diag_action, uint32_t length, uint32_t *return_code,
 274     int ioctl_mode);
 275 static int mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *data,
 276     int mode);
 277 
 278 static int mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
 279     int cmdlen, int tgtlen, int statuslen, int kf);
 280 static void mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd);
 281 
 282 static int mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags);
 283 static void mptsas_kmem_cache_destructor(void *buf, void *cdrarg);
 284 
 285 static int mptsas_cache_frames_constructor(void *buf, void *cdrarg,
 286     int kmflags);
 287 static void mptsas_cache_frames_destructor(void *buf, void *cdrarg);
 288 
 289 static void mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
 290     mptsas_cmd_t *cmd);
 291 static void mptsas_check_task_mgt(mptsas_t *mpt,
 292     pMpi2SCSIManagementReply_t reply, mptsas_cmd_t *cmd);
 293 static int mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
 294     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
 295     int *resid);
 296 
 297 static int mptsas_alloc_active_slots(mptsas_t *mpt, int flag);
 298 static void mptsas_free_active_slots(mptsas_t *mpt);
 299 static int mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 300 
 301 static void mptsas_restart_hba(mptsas_t *mpt);
 302 static void mptsas_restart_waitq(mptsas_t *mpt);
 303 
 304 static void mptsas_deliver_doneq_thread(mptsas_t *mpt);
 305 static void mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd);
 306 static void mptsas_doneq_mv(mptsas_t *mpt, uint64_t t);
 307 
 308 static mptsas_cmd_t *mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t);
 309 static void mptsas_doneq_empty(mptsas_t *mpt);
 310 static void mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg);
 311 
 312 static mptsas_cmd_t *mptsas_waitq_rm(mptsas_t *mpt);
 313 static void mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 314 static mptsas_cmd_t *mptsas_tx_waitq_rm(mptsas_t *mpt);
 315 static void mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd);
 316 
 317 
 318 static void mptsas_start_watch_reset_delay();
 319 static void mptsas_setup_bus_reset_delay(mptsas_t *mpt);
 320 static void mptsas_watch_reset_delay(void *arg);
 321 static int mptsas_watch_reset_delay_subr(mptsas_t *mpt);
 322 
 323 /*
 324  * helper functions
 325  */
 326 static void mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd);
 327 
 328 static dev_info_t *mptsas_find_child(dev_info_t *pdip, char *name);
 329 static dev_info_t *mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy);
 330 static dev_info_t *mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr,
 331     int lun);
 332 static mdi_pathinfo_t *mptsas_find_path_addr(dev_info_t *pdip, uint64_t sasaddr,
 333     int lun);
 334 static mdi_pathinfo_t *mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy);
 335 static dev_info_t *mptsas_find_smp_child(dev_info_t *pdip, char *str_wwn);
 336 
 337 static int mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy,
 338     int *lun);
 339 static int mptsas_parse_smp_name(char *name, uint64_t *wwn);
 340 
 341 static mptsas_target_t *mptsas_phy_to_tgt(mptsas_t *mpt,
 342     mptsas_phymask_t phymask, uint8_t phy);
 343 static mptsas_target_t *mptsas_wwid_to_ptgt(mptsas_t *mpt,
 344     mptsas_phymask_t phymask, uint64_t wwid);
 345 static mptsas_smp_t *mptsas_wwid_to_psmp(mptsas_t *mpt,
 346     mptsas_phymask_t phymask, uint64_t wwid);
 347 
 348 static int mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun,
 349     uchar_t page, unsigned char *buf, int len, int *rlen, uchar_t evpd);
 350 
 351 static int mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
 352     uint16_t *handle, mptsas_target_t **pptgt);
 353 static void mptsas_update_phymask(mptsas_t *mpt);
 354 
 355 static int mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
 356     uint32_t *status, uint8_t cmd);
 357 static dev_info_t *mptsas_get_dip_from_dev(dev_t dev,
 358     mptsas_phymask_t *phymask);
 359 static mptsas_target_t *mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr,
 360     mptsas_phymask_t phymask);
 361 static int mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt);
 362 
 363 
 364 /*
 365  * Enumeration / DR functions
 366  */
 367 static void mptsas_config_all(dev_info_t *pdip);
 368 static int mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
 369     dev_info_t **lundip);
 370 static int mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
 371     dev_info_t **lundip);
 372 
 373 static int mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt);
 374 static int mptsas_offline_target(dev_info_t *pdip, char *name);
 375 
 376 static int mptsas_config_raid(dev_info_t *pdip, uint16_t target,
 377     dev_info_t **dip);
 378 
 379 static int mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt);
 380 static int mptsas_probe_lun(dev_info_t *pdip, int lun,
 381     dev_info_t **dip, mptsas_target_t *ptgt);
 382 
 383 static int mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
 384     dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 385 
 386 static int mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 387     char *guid, dev_info_t **dip, mptsas_target_t *ptgt, int lun);
 388 static int mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *sd,
 389     char *guid, dev_info_t **dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt,
 390     int lun);
 391 
 392 static void mptsas_offline_missed_luns(dev_info_t *pdip,
 393     uint16_t *repluns, int lun_cnt, mptsas_target_t *ptgt);
 394 static int mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
 395     mdi_pathinfo_t *rpip, uint_t flags);
 396 
 397 static int mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn,
 398     dev_info_t **smp_dip);
 399 static int mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 400     uint_t flags);
 401 
 402 static int mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data,
 403     int mode, int *rval);
 404 static int mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data,
 405     int mode, int *rval);
 406 static int mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data,
 407     int mode, int *rval);
 408 static void mptsas_record_event(void *args);
 409 static int mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data,
 410     int mode);
 411 
 412 mptsas_target_t *mptsas_tgt_alloc(mptsas_t *, uint16_t, uint64_t,
 413     uint32_t, mptsas_phymask_t, uint8_t);
 414 static mptsas_smp_t *mptsas_smp_alloc(mptsas_t *, mptsas_smp_t *);
 415 static int mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
 416     dev_info_t **smp_dip);
 417 
 418 /*
 419  * Power management functions
 420  */
 421 static int mptsas_get_pci_cap(mptsas_t *mpt);
 422 static int mptsas_init_pm(mptsas_t *mpt);
 423 
 424 /*
 425  * MPT MSI tunable:
 426  *
 427  * By default MSI is enabled on all supported platforms.
 428  */
 429 boolean_t mptsas_enable_msi = B_TRUE;
 430 boolean_t mptsas_physical_bind_failed_page_83 = B_FALSE;
 431 
 432 /*
 433  * Global switch for use of MPI2.5 FAST PATH.
 434  * We don't really know what FAST PATH actually does, so if it is suspected
 435  * to cause problems it can be turned off by setting this variable to B_FALSE.
 436  */
 437 boolean_t mptsas_use_fastpath = B_TRUE;
 438 
 439 static int mptsas_register_intrs(mptsas_t *);
 440 static void mptsas_unregister_intrs(mptsas_t *);
 441 static int mptsas_add_intrs(mptsas_t *, int);
 442 static void mptsas_rem_intrs(mptsas_t *);
 443 
 444 /*
 445  * FMA Prototypes
 446  */
 447 static void mptsas_fm_init(mptsas_t *mpt);
 448 static void mptsas_fm_fini(mptsas_t *mpt);
 449 static int mptsas_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *);
 450 
 451 extern pri_t minclsyspri, maxclsyspri;
 452 
 453 /*
 454  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 455  * under this device that the paths to a physical device are created when
 456  * MPxIO is used.
 457  */
 458 extern dev_info_t       *scsi_vhci_dip;
 459 
 460 /*
 461  * Tunable timeout value for Inquiry VPD page 0x83
 462  * By default the value is 30 seconds.
 463  */
 464 int mptsas_inq83_retry_timeout = 30;
 465 
 466 /*
 467  * This is used to allocate memory for message frame storage, not for
 468  * data I/O DMA. All message frames must be stored in the first 4G of
 469  * physical memory.
 470  */
 471 ddi_dma_attr_t mptsas_dma_attrs = {
 472         DMA_ATTR_V0,    /* attribute layout version             */
 473         0x0ull,         /* address low - should be 0 (longlong) */
 474         0xffffffffull,  /* address high - 32-bit max range      */
 475         0x00ffffffull,  /* count max - max DMA object size      */
 476         4,              /* allocation alignment requirements    */
 477         0x78,           /* burstsizes - binary encoded values   */
 478         1,              /* minxfer - gran. of DMA engine        */
 479         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 480         0xffffffffull,  /* max segment size (DMA boundary)      */
 481         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 482         512,            /* granularity - device transfer size   */
 483         0               /* flags, set to 0                      */
 484 };
 485 
 486 /*
 487  * This is used for data I/O DMA memory allocation. (full 64-bit DMA
 488  * physical addresses are supported.)
 489  */
 490 ddi_dma_attr_t mptsas_dma_attrs64 = {
 491         DMA_ATTR_V0,    /* attribute layout version             */
 492         0x0ull,         /* address low - should be 0 (longlong) */
 493         0xffffffffffffffffull,  /* address high - 64-bit max    */
 494         0x00ffffffull,  /* count max - max DMA object size      */
 495         4,              /* allocation alignment requirements    */
 496         0x78,           /* burstsizes - binary encoded values   */
 497         1,              /* minxfer - gran. of DMA engine        */
 498         0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 499         0xffffffffull,  /* max segment size (DMA boundary)      */
 500         MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 501         512,            /* granularity - device transfer size   */
 502         DDI_DMA_RELAXED_ORDERING        /* flags, enable relaxed ordering */
 503 };
 504 
 505 ddi_device_acc_attr_t mptsas_dev_attr = {
 506         DDI_DEVICE_ATTR_V1,
 507         DDI_STRUCTURE_LE_ACC,
 508         DDI_STRICTORDER_ACC,
 509         DDI_DEFAULT_ACC
 510 };
 511 
 512 static struct cb_ops mptsas_cb_ops = {
 513         scsi_hba_open,          /* open */
 514         scsi_hba_close,         /* close */
 515         nodev,                  /* strategy */
 516         nodev,                  /* print */
 517         nodev,                  /* dump */
 518         nodev,                  /* read */
 519         nodev,                  /* write */
 520         mptsas_ioctl,           /* ioctl */
 521         nodev,                  /* devmap */
 522         nodev,                  /* mmap */
 523         nodev,                  /* segmap */
 524         nochpoll,               /* chpoll */
 525         ddi_prop_op,            /* cb_prop_op */
 526         NULL,                   /* streamtab */
 527         D_MP,                   /* cb_flag */
 528         CB_REV,                 /* rev */
 529         nodev,                  /* aread */
 530         nodev                   /* awrite */
 531 };
 532 
 533 static struct dev_ops mptsas_ops = {
 534         DEVO_REV,               /* devo_rev, */
 535         0,                      /* refcnt  */
 536         ddi_no_info,            /* info */
 537         nulldev,                /* identify */
 538         nulldev,                /* probe */
 539         mptsas_attach,          /* attach */
 540         mptsas_detach,          /* detach */
 541 #ifdef  __sparc
 542         mptsas_reset,
 543 #else
 544         nodev,                  /* reset */
 545 #endif  /* __sparc */
 546         &mptsas_cb_ops,             /* driver operations */
 547         NULL,                   /* bus operations */
 548         mptsas_power,           /* power management */
 549 #ifdef  __sparc
 550         ddi_quiesce_not_needed
 551 #else
 552         mptsas_quiesce          /* quiesce */
 553 #endif  /* __sparc */
 554 };
 555 
 556 
 557 #define MPTSAS_MOD_STRING "MPTSAS HBA Driver 00.00.00.24"
 558 
 559 static struct modldrv modldrv = {
 560         &mod_driverops,     /* Type of module. This one is a driver */
 561         MPTSAS_MOD_STRING, /* Name of the module. */
 562         &mptsas_ops,        /* driver ops */
 563 };
 564 
 565 static struct modlinkage modlinkage = {
 566         MODREV_1, &modldrv, NULL
 567 };
 568 #define TARGET_PROP     "target"
 569 #define LUN_PROP        "lun"
 570 #define LUN64_PROP      "lun64"
 571 #define SAS_PROP        "sas-mpt"
 572 #define MDI_GUID        "wwn"
 573 #define NDI_GUID        "guid"
 574 #define MPTSAS_DEV_GONE "mptsas_dev_gone"
 575 
 576 /*
 577  * Local static data
 578  */
 579 #if defined(MPTSAS_DEBUG)
 580 /*
 581  * Flags to indicate which debug messages are to be printed and which go to the
 582  * debug log ring buffer. Default is to not print anything, and to log
 583  * everything except the watchsubr() output which normally happens every second.
 584  */
 585 uint32_t mptsas_debugprt_flags = 0x0;
 586 uint32_t mptsas_debuglog_flags = ~(1U << 30);
 587 #endif  /* defined(MPTSAS_DEBUG) */
 588 uint32_t mptsas_debug_resets = 0;
 589 
 590 static kmutex_t         mptsas_global_mutex;
 591 static void             *mptsas_state;          /* soft state ptr */
 592 static krwlock_t        mptsas_global_rwlock;
 593 
 594 static kmutex_t         mptsas_log_mutex;
 595 static char             mptsas_log_buf[256];
 596 _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
 597 
 598 static mptsas_t *mptsas_head, *mptsas_tail;
 599 static clock_t mptsas_scsi_watchdog_tick;
 600 static clock_t mptsas_tick;
 601 static timeout_id_t mptsas_reset_watch;
 602 static timeout_id_t mptsas_timeout_id;
 603 static int mptsas_timeouts_enabled = 0;
 604 /*
 605  * warlock directives
 606  */
 607 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
 608         mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
 609 _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
 610 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
 611 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
 612 _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
 613 
 614 /*
 615  * SM - HBA statics
 616  */
 617 char    *mptsas_driver_rev = MPTSAS_MOD_STRING;
 618 
 619 #ifdef MPTSAS_DEBUG
 620 void debug_enter(char *);
 621 #endif
 622 
 623 /*
 624  * Notes:
 625  *      - scsi_hba_init(9F) initializes SCSI HBA modules
 626  *      - must call scsi_hba_fini(9F) if modload() fails
 627  */
 628 int
 629 _init(void)
 630 {
 631         int status;
 632         /* CONSTCOND */
 633         ASSERT(NO_COMPETING_THREADS);
 634 
 635         NDBG0(("_init"));
 636 
 637         status = ddi_soft_state_init(&mptsas_state, MPTSAS_SIZE,
 638             MPTSAS_INITIAL_SOFT_SPACE);
 639         if (status != 0) {
 640                 return (status);
 641         }
 642 
 643         if ((status = scsi_hba_init(&modlinkage)) != 0) {
 644                 ddi_soft_state_fini(&mptsas_state);
 645                 return (status);
 646         }
 647 
 648         mutex_init(&mptsas_global_mutex, NULL, MUTEX_DRIVER, NULL);
 649         rw_init(&mptsas_global_rwlock, NULL, RW_DRIVER, NULL);
 650         mutex_init(&mptsas_log_mutex, NULL, MUTEX_DRIVER, NULL);
 651 
 652         if ((status = mod_install(&modlinkage)) != 0) {
 653                 mutex_destroy(&mptsas_log_mutex);
 654                 rw_destroy(&mptsas_global_rwlock);
 655                 mutex_destroy(&mptsas_global_mutex);
 656                 ddi_soft_state_fini(&mptsas_state);
 657                 scsi_hba_fini(&modlinkage);
 658         }
 659 
 660         return (status);
 661 }
 662 
 663 /*
 664  * Notes:
 665  *      - scsi_hba_fini(9F) uninitializes SCSI HBA modules
 666  */
 667 int
 668 _fini(void)
 669 {
 670         int     status;
 671         /* CONSTCOND */
 672         ASSERT(NO_COMPETING_THREADS);
 673 
 674         NDBG0(("_fini"));
 675 
 676         if ((status = mod_remove(&modlinkage)) == 0) {
 677                 ddi_soft_state_fini(&mptsas_state);
 678                 scsi_hba_fini(&modlinkage);
 679                 mutex_destroy(&mptsas_global_mutex);
 680                 rw_destroy(&mptsas_global_rwlock);
 681                 mutex_destroy(&mptsas_log_mutex);
 682         }
 683         return (status);
 684 }
 685 
 686 /*
 687  * The loadable-module _info(9E) entry point
 688  */
 689 int
 690 _info(struct modinfo *modinfop)
 691 {
 692         /* CONSTCOND */
 693         ASSERT(NO_COMPETING_THREADS);
 694         NDBG0(("mptsas _info"));
 695 
 696         return (mod_info(&modlinkage, modinfop));
 697 }
 698 
 699 static int
 700 mptsas_target_eval_devhdl(const void *op, void *arg)
 701 {
 702         uint16_t dh = *(uint16_t *)arg;
 703         const mptsas_target_t *tp = op;
 704 
 705         return ((int)tp->m_devhdl - (int)dh);
 706 }
 707 
 708 static int
 709 mptsas_target_eval_slot(const void *op, void *arg)
 710 {
 711         mptsas_led_control_t *lcp = arg;
 712         const mptsas_target_t *tp = op;
 713 
 714         if (tp->m_enclosure != lcp->Enclosure)
 715                 return ((int)tp->m_enclosure - (int)lcp->Enclosure);
 716 
 717         return ((int)tp->m_slot_num - (int)lcp->Slot);
 718 }
 719 
 720 static int
 721 mptsas_target_eval_nowwn(const void *op, void *arg)
 722 {
 723         uint8_t phy = *(uint8_t *)arg;
 724         const mptsas_target_t *tp = op;
 725 
 726         if (tp->m_addr.mta_wwn != 0)
 727                 return (-1);
 728 
 729         return ((int)tp->m_phynum - (int)phy);
 730 }
 731 
 732 static int
 733 mptsas_smp_eval_devhdl(const void *op, void *arg)
 734 {
 735         uint16_t dh = *(uint16_t *)arg;
 736         const mptsas_smp_t *sp = op;
 737 
 738         return ((int)sp->m_devhdl - (int)dh);
 739 }
 740 
 741 static uint64_t
 742 mptsas_target_addr_hash(const void *tp)
 743 {
 744         const mptsas_target_addr_t *tap = tp;
 745 
 746         return ((tap->mta_wwn & 0xffffffffffffULL) |
 747             ((uint64_t)tap->mta_phymask << 48));
 748 }
 749 
 750 static int
 751 mptsas_target_addr_cmp(const void *a, const void *b)
 752 {
 753         const mptsas_target_addr_t *aap = a;
 754         const mptsas_target_addr_t *bap = b;
 755 
 756         if (aap->mta_wwn < bap->mta_wwn)
 757                 return (-1);
 758         if (aap->mta_wwn > bap->mta_wwn)
 759                 return (1);
 760         return ((int)bap->mta_phymask - (int)aap->mta_phymask);
 761 }
 762 
 763 static void
 764 mptsas_target_free(void *op)
 765 {
 766         kmem_free(op, sizeof (mptsas_target_t));
 767 }
 768 
 769 static void
 770 mptsas_smp_free(void *op)
 771 {
 772         kmem_free(op, sizeof (mptsas_smp_t));
 773 }
 774 
 775 static void
 776 mptsas_destroy_hashes(mptsas_t *mpt)
 777 {
 778         mptsas_target_t *tp;
 779         mptsas_smp_t *sp;
 780 
 781         for (tp = refhash_first(mpt->m_targets); tp != NULL;
 782             tp = refhash_next(mpt->m_targets, tp)) {
 783                 refhash_remove(mpt->m_targets, tp);
 784         }
 785         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
 786             sp = refhash_next(mpt->m_smp_targets, sp)) {
 787                 refhash_remove(mpt->m_smp_targets, sp);
 788         }
 789         refhash_destroy(mpt->m_targets);
 790         refhash_destroy(mpt->m_smp_targets);
 791         mpt->m_targets = NULL;
 792         mpt->m_smp_targets = NULL;
 793 }
 794 
 795 static int
 796 mptsas_iport_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 797 {
 798         dev_info_t              *pdip;
 799         mptsas_t                *mpt;
 800         scsi_hba_tran_t         *hba_tran;
 801         char                    *iport = NULL;
 802         char                    phymask[MPTSAS_MAX_PHYS];
 803         mptsas_phymask_t        phy_mask = 0;
 804         int                     dynamic_port = 0;
 805         uint32_t                page_address;
 806         char                    initiator_wwnstr[MPTSAS_WWN_STRLEN];
 807         int                     rval = DDI_FAILURE;
 808         int                     i = 0;
 809         uint8_t                 numphys = 0;
 810         uint8_t                 phy_id;
 811         uint8_t                 phy_port = 0;
 812         uint16_t                attached_devhdl = 0;
 813         uint32_t                dev_info;
 814         uint64_t                attached_sas_wwn;
 815         uint16_t                dev_hdl;
 816         uint16_t                pdev_hdl;
 817         uint16_t                bay_num, enclosure, io_flags;
 818         char                    attached_wwnstr[MPTSAS_WWN_STRLEN];
 819 
 820         /* CONSTCOND */
 821         ASSERT(NO_COMPETING_THREADS);
 822 
 823         switch (cmd) {
 824         case DDI_ATTACH:
 825                 break;
 826 
 827         case DDI_RESUME:
 828                 /*
 829                  * If this a scsi-iport node, nothing to do here.
 830                  */
 831                 return (DDI_SUCCESS);
 832 
 833         default:
 834                 return (DDI_FAILURE);
 835         }
 836 
 837         pdip = ddi_get_parent(dip);
 838 
 839         if ((hba_tran = ndi_flavorv_get(pdip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 840             NULL) {
 841                 cmn_err(CE_WARN, "Failed attach iport because fail to "
 842                     "get tran vector for the HBA node");
 843                 return (DDI_FAILURE);
 844         }
 845 
 846         mpt = TRAN2MPT(hba_tran);
 847         ASSERT(mpt != NULL);
 848         if (mpt == NULL)
 849                 return (DDI_FAILURE);
 850 
 851         if ((hba_tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) ==
 852             NULL) {
 853                 mptsas_log(mpt, CE_WARN, "Failed attach iport because fail to "
 854                     "get tran vector for the iport node");
 855                 return (DDI_FAILURE);
 856         }
 857 
 858         /*
 859          * Overwrite parent's tran_hba_private to iport's tran vector
 860          */
 861         hba_tran->tran_hba_private = mpt;
 862 
 863         ddi_report_dev(dip);
 864 
 865         /*
 866          * Get SAS address for initiator port according dev_handle
 867          */
 868         iport = ddi_get_name_addr(dip);
 869         if (iport && strncmp(iport, "v0", 2) == 0) {
 870                 if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 871                     MPTSAS_VIRTUAL_PORT, 1) !=
 872                     DDI_PROP_SUCCESS) {
 873                         (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 874                             MPTSAS_VIRTUAL_PORT);
 875                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 876                             "prop update failed");
 877                         return (DDI_FAILURE);
 878                 }
 879                 return (DDI_SUCCESS);
 880         }
 881 
 882         mutex_enter(&mpt->m_mutex);
 883         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 884                 bzero(phymask, sizeof (phymask));
 885                 (void) sprintf(phymask,
 886                     "%x", mpt->m_phy_info[i].phy_mask);
 887                 if (strcmp(phymask, iport) == 0) {
 888                         break;
 889                 }
 890         }
 891 
 892         if (i == MPTSAS_MAX_PHYS) {
 893                 mptsas_log(mpt, CE_WARN, "Failed attach port %s because port"
 894                     "seems not exist", iport);
 895                 mutex_exit(&mpt->m_mutex);
 896                 return (DDI_FAILURE);
 897         }
 898 
 899         phy_mask = mpt->m_phy_info[i].phy_mask;
 900 
 901         if (mpt->m_phy_info[i].port_flags & AUTO_PORT_CONFIGURATION)
 902                 dynamic_port = 1;
 903         else
 904                 dynamic_port = 0;
 905 
 906         /*
 907          * Update PHY info for smhba
 908          */
 909         if (mptsas_smhba_phy_init(mpt)) {
 910                 mutex_exit(&mpt->m_mutex);
 911                 mptsas_log(mpt, CE_WARN, "mptsas phy update "
 912                     "failed");
 913                 return (DDI_FAILURE);
 914         }
 915 
 916         mutex_exit(&mpt->m_mutex);
 917 
 918         numphys = 0;
 919         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 920                 if ((phy_mask >> i) & 0x01) {
 921                         numphys++;
 922                 }
 923         }
 924 
 925         bzero(initiator_wwnstr, sizeof (initiator_wwnstr));
 926         (void) sprintf(initiator_wwnstr, "w%016"PRIx64,
 927             mpt->un.m_base_wwid);
 928 
 929         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 930             SCSI_ADDR_PROP_INITIATOR_PORT, initiator_wwnstr) !=
 931             DDI_PROP_SUCCESS) {
 932                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
 933                     dip, SCSI_ADDR_PROP_INITIATOR_PORT);
 934                 mptsas_log(mpt, CE_WARN, "mptsas Initiator port "
 935                     "prop update failed");
 936                 return (DDI_FAILURE);
 937         }
 938         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 939             MPTSAS_NUM_PHYS, numphys) !=
 940             DDI_PROP_SUCCESS) {
 941                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, MPTSAS_NUM_PHYS);
 942                 return (DDI_FAILURE);
 943         }
 944 
 945         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 946             "phymask", phy_mask) !=
 947             DDI_PROP_SUCCESS) {
 948                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "phymask");
 949                 mptsas_log(mpt, CE_WARN, "mptsas phy mask "
 950                     "prop update failed");
 951                 return (DDI_FAILURE);
 952         }
 953 
 954         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 955             "dynamic-port", dynamic_port) !=
 956             DDI_PROP_SUCCESS) {
 957                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "dynamic-port");
 958                 mptsas_log(mpt, CE_WARN, "mptsas dynamic port "
 959                     "prop update failed");
 960                 return (DDI_FAILURE);
 961         }
 962         if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
 963             MPTSAS_VIRTUAL_PORT, 0) !=
 964             DDI_PROP_SUCCESS) {
 965                 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
 966                     MPTSAS_VIRTUAL_PORT);
 967                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
 968                     "prop update failed");
 969                 return (DDI_FAILURE);
 970         }
 971         mptsas_smhba_set_all_phy_props(mpt, dip, numphys, phy_mask,
 972             &attached_devhdl);
 973 
 974         mutex_enter(&mpt->m_mutex);
 975         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
 976             MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)attached_devhdl;
 977         rval = mptsas_get_sas_device_page0(mpt, page_address, &dev_hdl,
 978             &attached_sas_wwn, &dev_info, &phy_port, &phy_id,
 979             &pdev_hdl, &bay_num, &enclosure, &io_flags);
 980         if (rval != DDI_SUCCESS) {
 981                 mptsas_log(mpt, CE_WARN,
 982                     "Failed to get device page0 for handle:%d",
 983                     attached_devhdl);
 984                 mutex_exit(&mpt->m_mutex);
 985                 return (DDI_FAILURE);
 986         }
 987 
 988         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
 989                 bzero(phymask, sizeof (phymask));
 990                 (void) sprintf(phymask, "%x", mpt->m_phy_info[i].phy_mask);
 991                 if (strcmp(phymask, iport) == 0) {
 992                         (void) sprintf(&mpt->m_phy_info[i].smhba_info.path[0],
 993                             "%x",
 994                             mpt->m_phy_info[i].phy_mask);
 995                 }
 996         }
 997         mutex_exit(&mpt->m_mutex);
 998 
 999         bzero(attached_wwnstr, sizeof (attached_wwnstr));
1000         (void) sprintf(attached_wwnstr, "w%016"PRIx64,
1001             attached_sas_wwn);
1002         if (ddi_prop_update_string(DDI_DEV_T_NONE, dip,
1003             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
1004             DDI_PROP_SUCCESS) {
1005                 (void) ddi_prop_remove(DDI_DEV_T_NONE,
1006                     dip, SCSI_ADDR_PROP_ATTACHED_PORT);
1007                 return (DDI_FAILURE);
1008         }
1009 
1010         /* Create kstats for each phy on this iport */
1011 
1012         mptsas_create_phy_stats(mpt, iport, dip);
1013 
1014         /*
1015          * register sas hba iport with mdi (MPxIO/vhci)
1016          */
1017         if (mdi_phci_register(MDI_HCI_CLASS_SCSI,
1018             dip, 0) == MDI_SUCCESS) {
1019                 mpt->m_mpxio_enable = TRUE;
1020         }
1021         return (DDI_SUCCESS);
1022 }
1023 
1024 /*
1025  * Notes:
1026  *      Set up all device state and allocate data structures,
1027  *      mutexes, condition variables, etc. for device operation.
1028  *      Add interrupts needed.
1029  *      Return DDI_SUCCESS if device is ready, else return DDI_FAILURE.
1030  */
1031 static int
1032 mptsas_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1033 {
1034         mptsas_t                *mpt = NULL;
1035         int                     instance, i, j;
1036         int                     doneq_thread_num;
1037         char                    intr_added = 0;
1038         char                    map_setup = 0;
1039         char                    config_setup = 0;
1040         char                    hba_attach_setup = 0;
1041         char                    smp_attach_setup = 0;
1042         char                    mutex_init_done = 0;
1043         char                    event_taskq_create = 0;
1044         char                    dr_taskq_create = 0;
1045         char                    doneq_thread_create = 0;
1046         char                    added_watchdog = 0;
1047         scsi_hba_tran_t         *hba_tran;
1048         uint_t                  mem_bar = MEM_SPACE;
1049         int                     rval = DDI_FAILURE;
1050 
1051         /* CONSTCOND */
1052         ASSERT(NO_COMPETING_THREADS);
1053 
1054         if (scsi_hba_iport_unit_address(dip)) {
1055                 return (mptsas_iport_attach(dip, cmd));
1056         }
1057 
1058         switch (cmd) {
1059         case DDI_ATTACH:
1060                 break;
1061 
1062         case DDI_RESUME:
1063                 if ((hba_tran = ddi_get_driver_private(dip)) == NULL)
1064                         return (DDI_FAILURE);
1065 
1066                 mpt = TRAN2MPT(hba_tran);
1067 
1068                 if (!mpt) {
1069                         return (DDI_FAILURE);
1070                 }
1071 
1072                 /*
1073                  * Reset hardware and softc to "no outstanding commands"
1074                  * Note that a check condition can result on first command
1075                  * to a target.
1076                  */
1077                 mutex_enter(&mpt->m_mutex);
1078 
1079                 /*
1080                  * raise power.
1081                  */
1082                 if (mpt->m_options & MPTSAS_OPT_PM) {
1083                         mutex_exit(&mpt->m_mutex);
1084                         (void) pm_busy_component(dip, 0);
1085                         rval = pm_power_has_changed(dip, 0, PM_LEVEL_D0);
1086                         if (rval == DDI_SUCCESS) {
1087                                 mutex_enter(&mpt->m_mutex);
1088                         } else {
1089                                 /*
1090                                  * The pm_raise_power() call above failed,
1091                                  * and that can only occur if we were unable
1092                                  * to reset the hardware.  This is probably
1093                                  * due to unhealty hardware, and because
1094                                  * important filesystems(such as the root
1095                                  * filesystem) could be on the attached disks,
1096                                  * it would not be a good idea to continue,
1097                                  * as we won't be entirely certain we are
1098                                  * writing correct data.  So we panic() here
1099                                  * to not only prevent possible data corruption,
1100                                  * but to give developers or end users a hope
1101                                  * of identifying and correcting any problems.
1102                                  */
1103                                 fm_panic("mptsas could not reset hardware "
1104                                     "during resume");
1105                         }
1106                 }
1107 
1108                 mpt->m_suspended = 0;
1109 
1110                 /*
1111                  * Reinitialize ioc
1112                  */
1113                 mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1114                 if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
1115                         mutex_exit(&mpt->m_mutex);
1116                         if (mpt->m_options & MPTSAS_OPT_PM) {
1117                                 (void) pm_idle_component(dip, 0);
1118                         }
1119                         fm_panic("mptsas init chip fail during resume");
1120                 }
1121                 /*
1122                  * mptsas_update_driver_data needs interrupts so enable them
1123                  * first.
1124                  */
1125                 MPTSAS_ENABLE_INTR(mpt);
1126                 mptsas_update_driver_data(mpt);
1127 
1128                 /* start requests, if possible */
1129                 mptsas_restart_hba(mpt);
1130 
1131                 mutex_exit(&mpt->m_mutex);
1132 
1133                 /*
1134                  * Restart watch thread
1135                  */
1136                 mutex_enter(&mptsas_global_mutex);
1137                 if (mptsas_timeout_id == 0) {
1138                         mptsas_timeout_id = timeout(mptsas_watch, NULL,
1139                             mptsas_tick);
1140                         mptsas_timeouts_enabled = 1;
1141                 }
1142                 mutex_exit(&mptsas_global_mutex);
1143 
1144                 /* report idle status to pm framework */
1145                 if (mpt->m_options & MPTSAS_OPT_PM) {
1146                         (void) pm_idle_component(dip, 0);
1147                 }
1148 
1149                 return (DDI_SUCCESS);
1150 
1151         default:
1152                 return (DDI_FAILURE);
1153 
1154         }
1155 
1156         instance = ddi_get_instance(dip);
1157 
1158         /*
1159          * Allocate softc information.
1160          */
1161         if (ddi_soft_state_zalloc(mptsas_state, instance) != DDI_SUCCESS) {
1162                 mptsas_log(NULL, CE_WARN,
1163                     "mptsas%d: cannot allocate soft state", instance);
1164                 goto fail;
1165         }
1166 
1167         mpt = ddi_get_soft_state(mptsas_state, instance);
1168 
1169         if (mpt == NULL) {
1170                 mptsas_log(NULL, CE_WARN,
1171                     "mptsas%d: cannot get soft state", instance);
1172                 goto fail;
1173         }
1174 
1175         /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1176         scsi_size_clean(dip);
1177 
1178         mpt->m_dip = dip;
1179         mpt->m_instance = instance;
1180 
1181         /* Make a per-instance copy of the structures */
1182         mpt->m_io_dma_attr = mptsas_dma_attrs64;
1183         mpt->m_msg_dma_attr = mptsas_dma_attrs;
1184         mpt->m_reg_acc_attr = mptsas_dev_attr;
1185         mpt->m_dev_acc_attr = mptsas_dev_attr;
1186 
1187         /*
1188          * Initialize FMA
1189          */
1190         mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1191             DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1192             DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1193             DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
1194 
1195         mptsas_fm_init(mpt);
1196 
1197         if (mptsas_alloc_handshake_msg(mpt,
1198             sizeof (Mpi2SCSITaskManagementRequest_t)) == DDI_FAILURE) {
1199                 mptsas_log(mpt, CE_WARN, "cannot initialize handshake msg.");
1200                 goto fail;
1201         }
1202 
1203         /*
1204          * Setup configuration space
1205          */
1206         if (mptsas_config_space_init(mpt) == FALSE) {
1207                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init failed");
1208                 goto fail;
1209         }
1210         config_setup++;
1211 
1212         if (ddi_regs_map_setup(dip, mem_bar, (caddr_t *)&mpt->m_reg,
1213             0, 0, &mpt->m_reg_acc_attr, &mpt->m_datap) != DDI_SUCCESS) {
1214                 mptsas_log(mpt, CE_WARN, "map setup failed");
1215                 goto fail;
1216         }
1217         map_setup++;
1218 
1219         /*
1220          * A taskq is created for dealing with the event handler
1221          */
1222         if ((mpt->m_event_taskq = ddi_taskq_create(dip, "mptsas_event_taskq",
1223             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1224                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create failed");
1225                 goto fail;
1226         }
1227         event_taskq_create++;
1228 
1229         /*
1230          * A taskq is created for dealing with dr events
1231          */
1232         if ((mpt->m_dr_taskq = ddi_taskq_create(dip,
1233             "mptsas_dr_taskq",
1234             1, TASKQ_DEFAULTPRI, 0)) == NULL) {
1235                 mptsas_log(mpt, CE_NOTE, "ddi_taskq_create for discovery "
1236                     "failed");
1237                 goto fail;
1238         }
1239         dr_taskq_create++;
1240 
1241         mpt->m_doneq_thread_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1242             0, "mptsas_doneq_thread_threshold_prop", 10);
1243         mpt->m_doneq_length_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1244             0, "mptsas_doneq_length_threshold_prop", 8);
1245         mpt->m_doneq_thread_n = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
1246             0, "mptsas_doneq_thread_n_prop", 8);
1247 
1248         if (mpt->m_doneq_thread_n) {
1249                 cv_init(&mpt->m_doneq_thread_cv, NULL, CV_DRIVER, NULL);
1250                 mutex_init(&mpt->m_doneq_mutex, NULL, MUTEX_DRIVER, NULL);
1251 
1252                 mutex_enter(&mpt->m_doneq_mutex);
1253                 mpt->m_doneq_thread_id =
1254                     kmem_zalloc(sizeof (mptsas_doneq_thread_list_t)
1255                     * mpt->m_doneq_thread_n, KM_SLEEP);
1256 
1257                 for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1258                         cv_init(&mpt->m_doneq_thread_id[j].cv, NULL,
1259                             CV_DRIVER, NULL);
1260                         mutex_init(&mpt->m_doneq_thread_id[j].mutex, NULL,
1261                             MUTEX_DRIVER, NULL);
1262                         mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1263                         mpt->m_doneq_thread_id[j].flag |=
1264                             MPTSAS_DONEQ_THREAD_ACTIVE;
1265                         mpt->m_doneq_thread_id[j].arg.mpt = mpt;
1266                         mpt->m_doneq_thread_id[j].arg.t = j;
1267                         mpt->m_doneq_thread_id[j].threadp =
1268                             thread_create(NULL, 0, mptsas_doneq_thread,
1269                             &mpt->m_doneq_thread_id[j].arg,
1270                             0, &p0, TS_RUN, minclsyspri);
1271                         mpt->m_doneq_thread_id[j].donetail =
1272                             &mpt->m_doneq_thread_id[j].doneq;
1273                         mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1274                 }
1275                 mutex_exit(&mpt->m_doneq_mutex);
1276                 doneq_thread_create++;
1277         }
1278 
1279         /*
1280          * Disable hardware interrupt since we're not ready to
1281          * handle it yet.
1282          */
1283         MPTSAS_DISABLE_INTR(mpt);
1284         if (mptsas_register_intrs(mpt) == FALSE)
1285                 goto fail;
1286         intr_added++;
1287 
1288         /* Initialize mutex used in interrupt handler */
1289         mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1290             DDI_INTR_PRI(mpt->m_intr_pri));
1291         mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1292         mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
1293             DDI_INTR_PRI(mpt->m_intr_pri));
1294         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1295                 mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1296                     NULL, MUTEX_DRIVER,
1297                     DDI_INTR_PRI(mpt->m_intr_pri));
1298         }
1299 
1300         cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1301         cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1302         cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1303         cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1304         cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1305         mutex_init_done++;
1306 
1307         mutex_enter(&mpt->m_mutex);
1308         /*
1309          * Initialize power management component
1310          */
1311         if (mpt->m_options & MPTSAS_OPT_PM) {
1312                 if (mptsas_init_pm(mpt)) {
1313                         mutex_exit(&mpt->m_mutex);
1314                         mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1315                             "failed");
1316                         goto fail;
1317                 }
1318         }
1319 
1320         /*
1321          * Initialize chip using Message Unit Reset, if allowed
1322          */
1323         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1324         if (mptsas_init_chip(mpt, TRUE) == DDI_FAILURE) {
1325                 mutex_exit(&mpt->m_mutex);
1326                 mptsas_log(mpt, CE_WARN, "mptsas chip initialization failed");
1327                 goto fail;
1328         }
1329 
1330         /*
1331          * Fill in the phy_info structure and get the base WWID
1332          */
1333         if (mptsas_get_manufacture_page5(mpt) == DDI_FAILURE) {
1334                 mptsas_log(mpt, CE_WARN,
1335                     "mptsas_get_manufacture_page5 failed!");
1336                 goto fail;
1337         }
1338 
1339         if (mptsas_get_sas_io_unit_page_hndshk(mpt)) {
1340                 mptsas_log(mpt, CE_WARN,
1341                     "mptsas_get_sas_io_unit_page_hndshk failed!");
1342                 goto fail;
1343         }
1344 
1345         if (mptsas_get_manufacture_page0(mpt) == DDI_FAILURE) {
1346                 mptsas_log(mpt, CE_WARN,
1347                     "mptsas_get_manufacture_page0 failed!");
1348                 goto fail;
1349         }
1350 
1351         mutex_exit(&mpt->m_mutex);
1352 
1353         /*
1354          * Register the iport for multiple port HBA
1355          */
1356         mptsas_iport_register(mpt);
1357 
1358         /*
1359          * initialize SCSI HBA transport structure
1360          */
1361         if (mptsas_hba_setup(mpt) == FALSE)
1362                 goto fail;
1363         hba_attach_setup++;
1364 
1365         if (mptsas_smp_setup(mpt) == FALSE)
1366                 goto fail;
1367         smp_attach_setup++;
1368 
1369         if (mptsas_cache_create(mpt) == FALSE)
1370                 goto fail;
1371 
1372         mpt->m_scsi_reset_delay      = ddi_prop_get_int(DDI_DEV_T_ANY,
1373             dip, 0, "scsi-reset-delay", SCSI_DEFAULT_RESET_DELAY);
1374         if (mpt->m_scsi_reset_delay == 0) {
1375                 mptsas_log(mpt, CE_NOTE,
1376                     "scsi_reset_delay of 0 is not recommended,"
1377                     " resetting to SCSI_DEFAULT_RESET_DELAY\n");
1378                 mpt->m_scsi_reset_delay = SCSI_DEFAULT_RESET_DELAY;
1379         }
1380 
1381         /*
1382          * Initialize the wait and done FIFO queue
1383          */
1384         mpt->m_donetail = &mpt->m_doneq;
1385         mpt->m_waitqtail = &mpt->m_waitq;
1386         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
1387         mpt->m_tx_draining = 0;
1388 
1389         /*
1390          * ioc cmd queue initialize
1391          */
1392         mpt->m_ioc_event_cmdtail = &mpt->m_ioc_event_cmdq;
1393         mpt->m_dev_handle = 0xFFFF;
1394 
1395         MPTSAS_ENABLE_INTR(mpt);
1396 
1397         /*
1398          * enable event notification
1399          */
1400         mutex_enter(&mpt->m_mutex);
1401         if (mptsas_ioc_enable_event_notification(mpt)) {
1402                 mutex_exit(&mpt->m_mutex);
1403                 goto fail;
1404         }
1405         mutex_exit(&mpt->m_mutex);
1406 
1407         /*
1408          * used for mptsas_watch
1409          */
1410         mptsas_list_add(mpt);
1411 
1412         mutex_enter(&mptsas_global_mutex);
1413         if (mptsas_timeouts_enabled == 0) {
1414                 mptsas_scsi_watchdog_tick = ddi_prop_get_int(DDI_DEV_T_ANY,
1415                     dip, 0, "scsi-watchdog-tick", DEFAULT_WD_TICK);
1416 
1417                 mptsas_tick = mptsas_scsi_watchdog_tick *
1418                     drv_usectohz((clock_t)1000000);
1419 
1420                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
1421                 mptsas_timeouts_enabled = 1;
1422         }
1423         mutex_exit(&mptsas_global_mutex);
1424         added_watchdog++;
1425 
1426         /*
1427          * Initialize PHY info for smhba.
1428          * This requires watchdog to be enabled otherwise if interrupts
1429          * don't work the system will hang.
1430          */
1431         if (mptsas_smhba_setup(mpt)) {
1432                 mptsas_log(mpt, CE_WARN, "mptsas phy initialization "
1433                     "failed");
1434                 goto fail;
1435         }
1436 
1437         /* Check all dma handles allocated in attach */
1438         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl)
1439             != DDI_SUCCESS) ||
1440             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl)
1441             != DDI_SUCCESS) ||
1442             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl)
1443             != DDI_SUCCESS) ||
1444             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl)
1445             != DDI_SUCCESS) ||
1446             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl)
1447             != DDI_SUCCESS)) {
1448                 goto fail;
1449         }
1450 
1451         /* Check all acc handles allocated in attach */
1452         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
1453             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl)
1454             != DDI_SUCCESS) ||
1455             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl)
1456             != DDI_SUCCESS) ||
1457             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl)
1458             != DDI_SUCCESS) ||
1459             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl)
1460             != DDI_SUCCESS) ||
1461             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl)
1462             != DDI_SUCCESS) ||
1463             (mptsas_check_acc_handle(mpt->m_config_handle)
1464             != DDI_SUCCESS)) {
1465                 goto fail;
1466         }
1467 
1468         /*
1469          * After this point, we are not going to fail the attach.
1470          */
1471 
1472         /* Print message of HBA present */
1473         ddi_report_dev(dip);
1474 
1475         /* report idle status to pm framework */
1476         if (mpt->m_options & MPTSAS_OPT_PM) {
1477                 (void) pm_idle_component(dip, 0);
1478         }
1479 
1480         return (DDI_SUCCESS);
1481 
1482 fail:
1483         mptsas_log(mpt, CE_WARN, "attach failed");
1484         mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
1485         ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
1486         if (mpt) {
1487                 /* deallocate in reverse order */
1488                 if (added_watchdog) {
1489                         mptsas_list_del(mpt);
1490                         mutex_enter(&mptsas_global_mutex);
1491 
1492                         if (mptsas_timeout_id && (mptsas_head == NULL)) {
1493                                 timeout_id_t tid = mptsas_timeout_id;
1494                                 mptsas_timeouts_enabled = 0;
1495                                 mptsas_timeout_id = 0;
1496                                 mutex_exit(&mptsas_global_mutex);
1497                                 (void) untimeout(tid);
1498                                 mutex_enter(&mptsas_global_mutex);
1499                         }
1500                         mutex_exit(&mptsas_global_mutex);
1501                 }
1502 
1503                 mptsas_cache_destroy(mpt);
1504 
1505                 if (smp_attach_setup) {
1506                         mptsas_smp_teardown(mpt);
1507                 }
1508                 if (hba_attach_setup) {
1509                         mptsas_hba_teardown(mpt);
1510                 }
1511 
1512                 if (mpt->m_targets)
1513                         refhash_destroy(mpt->m_targets);
1514                 if (mpt->m_smp_targets)
1515                         refhash_destroy(mpt->m_smp_targets);
1516 
1517                 if (mpt->m_active) {
1518                         mptsas_free_active_slots(mpt);
1519                 }
1520                 if (intr_added) {
1521                         mptsas_unregister_intrs(mpt);
1522                 }
1523 
1524                 if (doneq_thread_create) {
1525                         mutex_enter(&mpt->m_doneq_mutex);
1526                         doneq_thread_num = mpt->m_doneq_thread_n;
1527                         for (j = 0; j < mpt->m_doneq_thread_n; j++) {
1528                                 mutex_enter(&mpt->m_doneq_thread_id[j].mutex);
1529                                 mpt->m_doneq_thread_id[j].flag &=
1530                                     (~MPTSAS_DONEQ_THREAD_ACTIVE);
1531                                 cv_signal(&mpt->m_doneq_thread_id[j].cv);
1532                                 mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1533                         }
1534                         while (mpt->m_doneq_thread_n) {
1535                                 cv_wait(&mpt->m_doneq_thread_cv,
1536                                     &mpt->m_doneq_mutex);
1537                         }
1538                         for (j = 0; j < doneq_thread_num; j++) {
1539                                 cv_destroy(&mpt->m_doneq_thread_id[j].cv);
1540                                 mutex_destroy(&mpt->m_doneq_thread_id[j].mutex);
1541                         }
1542                         kmem_free(mpt->m_doneq_thread_id,
1543                             sizeof (mptsas_doneq_thread_list_t)
1544                             * doneq_thread_num);
1545                         mutex_exit(&mpt->m_doneq_mutex);
1546                         cv_destroy(&mpt->m_doneq_thread_cv);
1547                         mutex_destroy(&mpt->m_doneq_mutex);
1548                 }
1549                 if (event_taskq_create) {
1550                         ddi_taskq_destroy(mpt->m_event_taskq);
1551                 }
1552                 if (dr_taskq_create) {
1553                         ddi_taskq_destroy(mpt->m_dr_taskq);
1554                 }
1555                 if (mutex_init_done) {
1556                         mutex_destroy(&mpt->m_tx_waitq_mutex);
1557                         mutex_destroy(&mpt->m_passthru_mutex);
1558                         mutex_destroy(&mpt->m_mutex);
1559                         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1560                                 mutex_destroy(
1561                                     &mpt->m_phy_info[i].smhba_info.phy_mutex);
1562                         }
1563                         cv_destroy(&mpt->m_cv);
1564                         cv_destroy(&mpt->m_passthru_cv);
1565                         cv_destroy(&mpt->m_fw_cv);
1566                         cv_destroy(&mpt->m_config_cv);
1567                         cv_destroy(&mpt->m_fw_diag_cv);
1568                 }
1569 
1570                 if (map_setup) {
1571                         mptsas_cfg_fini(mpt);
1572                 }
1573                 if (config_setup) {
1574                         mptsas_config_space_fini(mpt);
1575                 }
1576                 mptsas_free_handshake_msg(mpt);
1577                 mptsas_hba_fini(mpt);
1578 
1579                 mptsas_fm_fini(mpt);
1580                 ddi_soft_state_free(mptsas_state, instance);
1581                 ddi_prop_remove_all(dip);
1582         }
1583         return (DDI_FAILURE);
1584 }
1585 
1586 static int
1587 mptsas_suspend(dev_info_t *devi)
1588 {
1589         mptsas_t        *mpt, *g;
1590         scsi_hba_tran_t *tran;
1591 
1592         if (scsi_hba_iport_unit_address(devi)) {
1593                 return (DDI_SUCCESS);
1594         }
1595 
1596         if ((tran = ddi_get_driver_private(devi)) == NULL)
1597                 return (DDI_SUCCESS);
1598 
1599         mpt = TRAN2MPT(tran);
1600         if (!mpt) {
1601                 return (DDI_SUCCESS);
1602         }
1603 
1604         mutex_enter(&mpt->m_mutex);
1605 
1606         if (mpt->m_suspended++) {
1607                 mutex_exit(&mpt->m_mutex);
1608                 return (DDI_SUCCESS);
1609         }
1610 
1611         /*
1612          * Cancel timeout threads for this mpt
1613          */
1614         if (mpt->m_quiesce_timeid) {
1615                 timeout_id_t tid = mpt->m_quiesce_timeid;
1616                 mpt->m_quiesce_timeid = 0;
1617                 mutex_exit(&mpt->m_mutex);
1618                 (void) untimeout(tid);
1619                 mutex_enter(&mpt->m_mutex);
1620         }
1621 
1622         if (mpt->m_restart_cmd_timeid) {
1623                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1624                 mpt->m_restart_cmd_timeid = 0;
1625                 mutex_exit(&mpt->m_mutex);
1626                 (void) untimeout(tid);
1627                 mutex_enter(&mpt->m_mutex);
1628         }
1629 
1630         mutex_exit(&mpt->m_mutex);
1631 
1632         (void) pm_idle_component(mpt->m_dip, 0);
1633 
1634         /*
1635          * Cancel watch threads if all mpts suspended
1636          */
1637         rw_enter(&mptsas_global_rwlock, RW_WRITER);
1638         for (g = mptsas_head; g != NULL; g = g->m_next) {
1639                 if (!g->m_suspended)
1640                         break;
1641         }
1642         rw_exit(&mptsas_global_rwlock);
1643 
1644         mutex_enter(&mptsas_global_mutex);
1645         if (g == NULL) {
1646                 timeout_id_t tid;
1647 
1648                 mptsas_timeouts_enabled = 0;
1649                 if (mptsas_timeout_id) {
1650                         tid = mptsas_timeout_id;
1651                         mptsas_timeout_id = 0;
1652                         mutex_exit(&mptsas_global_mutex);
1653                         (void) untimeout(tid);
1654                         mutex_enter(&mptsas_global_mutex);
1655                 }
1656                 if (mptsas_reset_watch) {
1657                         tid = mptsas_reset_watch;
1658                         mptsas_reset_watch = 0;
1659                         mutex_exit(&mptsas_global_mutex);
1660                         (void) untimeout(tid);
1661                         mutex_enter(&mptsas_global_mutex);
1662                 }
1663         }
1664         mutex_exit(&mptsas_global_mutex);
1665 
1666         mutex_enter(&mpt->m_mutex);
1667 
1668         /*
1669          * If this mpt is not in full power(PM_LEVEL_D0), just return.
1670          */
1671         if ((mpt->m_options & MPTSAS_OPT_PM) &&
1672             (mpt->m_power_level != PM_LEVEL_D0)) {
1673                 mutex_exit(&mpt->m_mutex);
1674                 return (DDI_SUCCESS);
1675         }
1676 
1677         /* Disable HBA interrupts in hardware */
1678         MPTSAS_DISABLE_INTR(mpt);
1679         /*
1680          * Send RAID action system shutdown to sync IR
1681          */
1682         mptsas_raid_action_system_shutdown(mpt);
1683 
1684         mutex_exit(&mpt->m_mutex);
1685 
1686         /* drain the taskq */
1687         ddi_taskq_wait(mpt->m_event_taskq);
1688         ddi_taskq_wait(mpt->m_dr_taskq);
1689 
1690         return (DDI_SUCCESS);
1691 }
1692 
1693 #ifdef  __sparc
1694 /*ARGSUSED*/
1695 static int
1696 mptsas_reset(dev_info_t *devi, ddi_reset_cmd_t cmd)
1697 {
1698         mptsas_t        *mpt;
1699         scsi_hba_tran_t *tran;
1700 
1701         /*
1702          * If this call is for iport, just return.
1703          */
1704         if (scsi_hba_iport_unit_address(devi))
1705                 return (DDI_SUCCESS);
1706 
1707         if ((tran = ddi_get_driver_private(devi)) == NULL)
1708                 return (DDI_SUCCESS);
1709 
1710         if ((mpt = TRAN2MPT(tran)) == NULL)
1711                 return (DDI_SUCCESS);
1712 
1713         /*
1714          * Send RAID action system shutdown to sync IR.  Disable HBA
1715          * interrupts in hardware first.
1716          */
1717         MPTSAS_DISABLE_INTR(mpt);
1718         mptsas_raid_action_system_shutdown(mpt);
1719 
1720         return (DDI_SUCCESS);
1721 }
1722 #else /* __sparc */
1723 /*
1724  * quiesce(9E) entry point.
1725  *
1726  * This function is called when the system is single-threaded at high
1727  * PIL with preemption disabled. Therefore, this function must not be
1728  * blocked.
1729  *
1730  * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1731  * DDI_FAILURE indicates an error condition and should almost never happen.
1732  */
1733 static int
1734 mptsas_quiesce(dev_info_t *devi)
1735 {
1736         mptsas_t        *mpt;
1737         scsi_hba_tran_t *tran;
1738 
1739         /*
1740          * If this call is for iport, just return.
1741          */
1742         if (scsi_hba_iport_unit_address(devi))
1743                 return (DDI_SUCCESS);
1744 
1745         if ((tran = ddi_get_driver_private(devi)) == NULL)
1746                 return (DDI_SUCCESS);
1747 
1748         if ((mpt = TRAN2MPT(tran)) == NULL)
1749                 return (DDI_SUCCESS);
1750 
1751         /* Disable HBA interrupts in hardware */
1752         MPTSAS_DISABLE_INTR(mpt);
1753         /* Send RAID action system shutdonw to sync IR */
1754         mptsas_raid_action_system_shutdown(mpt);
1755 
1756         return (DDI_SUCCESS);
1757 }
1758 #endif  /* __sparc */
1759 
1760 /*
1761  * detach(9E).  Remove all device allocations and system resources;
1762  * disable device interrupts.
1763  * Return DDI_SUCCESS if done; DDI_FAILURE if there's a problem.
1764  */
1765 static int
1766 mptsas_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1767 {
1768         /* CONSTCOND */
1769         ASSERT(NO_COMPETING_THREADS);
1770         NDBG0(("mptsas_detach: dip=0x%p cmd=0x%p", (void *)devi, (void *)cmd));
1771 
1772         switch (cmd) {
1773         case DDI_DETACH:
1774                 return (mptsas_do_detach(devi));
1775 
1776         case DDI_SUSPEND:
1777                 return (mptsas_suspend(devi));
1778 
1779         default:
1780                 return (DDI_FAILURE);
1781         }
1782         /* NOTREACHED */
1783 }
1784 
1785 static int
1786 mptsas_do_detach(dev_info_t *dip)
1787 {
1788         mptsas_t        *mpt;
1789         scsi_hba_tran_t *tran;
1790         int             circ = 0;
1791         int             circ1 = 0;
1792         mdi_pathinfo_t  *pip = NULL;
1793         int             i;
1794         int             doneq_thread_num = 0;
1795 
1796         NDBG0(("mptsas_do_detach: dip=0x%p", (void *)dip));
1797 
1798         if ((tran = ndi_flavorv_get(dip, SCSA_FLAVOR_SCSI_DEVICE)) == NULL)
1799                 return (DDI_FAILURE);
1800 
1801         mpt = TRAN2MPT(tran);
1802         if (!mpt) {
1803                 return (DDI_FAILURE);
1804         }
1805         /*
1806          * Still have pathinfo child, should not detach mpt driver
1807          */
1808         if (scsi_hba_iport_unit_address(dip)) {
1809                 if (mpt->m_mpxio_enable) {
1810                         /*
1811                          * MPxIO enabled for the iport
1812                          */
1813                         ndi_devi_enter(scsi_vhci_dip, &circ1);
1814                         ndi_devi_enter(dip, &circ);
1815                         while (pip = mdi_get_next_client_path(dip, NULL)) {
1816                                 if (mdi_pi_free(pip, 0) == MDI_SUCCESS) {
1817                                         continue;
1818                                 }
1819                                 ndi_devi_exit(dip, circ);
1820                                 ndi_devi_exit(scsi_vhci_dip, circ1);
1821                                 NDBG12(("detach failed because of "
1822                                     "outstanding path info"));
1823                                 return (DDI_FAILURE);
1824                         }
1825                         ndi_devi_exit(dip, circ);
1826                         ndi_devi_exit(scsi_vhci_dip, circ1);
1827                         (void) mdi_phci_unregister(dip, 0);
1828                 }
1829 
1830                 ddi_prop_remove_all(dip);
1831 
1832                 return (DDI_SUCCESS);
1833         }
1834 
1835         /* Make sure power level is D0 before accessing registers */
1836         if (mpt->m_options & MPTSAS_OPT_PM) {
1837                 (void) pm_busy_component(dip, 0);
1838                 if (mpt->m_power_level != PM_LEVEL_D0) {
1839                         if (pm_raise_power(dip, 0, PM_LEVEL_D0) !=
1840                             DDI_SUCCESS) {
1841                                 mptsas_log(mpt, CE_WARN,
1842                                     "mptsas%d: Raise power request failed.",
1843                                     mpt->m_instance);
1844                                 (void) pm_idle_component(dip, 0);
1845                                 return (DDI_FAILURE);
1846                         }
1847                 }
1848         }
1849 
1850         /*
1851          * Send RAID action system shutdown to sync IR.  After action, send a
1852          * Message Unit Reset. Since after that DMA resource will be freed,
1853          * set ioc to READY state will avoid HBA initiated DMA operation.
1854          */
1855         mutex_enter(&mpt->m_mutex);
1856         MPTSAS_DISABLE_INTR(mpt);
1857         mptsas_raid_action_system_shutdown(mpt);
1858         mpt->m_softstate |= MPTSAS_SS_MSG_UNIT_RESET;
1859         (void) mptsas_ioc_reset(mpt, FALSE);
1860         mutex_exit(&mpt->m_mutex);
1861         mptsas_rem_intrs(mpt);
1862         ddi_taskq_destroy(mpt->m_event_taskq);
1863         ddi_taskq_destroy(mpt->m_dr_taskq);
1864 
1865         if (mpt->m_doneq_thread_n) {
1866                 mutex_enter(&mpt->m_doneq_mutex);
1867                 doneq_thread_num = mpt->m_doneq_thread_n;
1868                 for (i = 0; i < mpt->m_doneq_thread_n; i++) {
1869                         mutex_enter(&mpt->m_doneq_thread_id[i].mutex);
1870                         mpt->m_doneq_thread_id[i].flag &=
1871                             (~MPTSAS_DONEQ_THREAD_ACTIVE);
1872                         cv_signal(&mpt->m_doneq_thread_id[i].cv);
1873                         mutex_exit(&mpt->m_doneq_thread_id[i].mutex);
1874                 }
1875                 while (mpt->m_doneq_thread_n) {
1876                         cv_wait(&mpt->m_doneq_thread_cv,
1877                             &mpt->m_doneq_mutex);
1878                 }
1879                 for (i = 0;  i < doneq_thread_num; i++) {
1880                         cv_destroy(&mpt->m_doneq_thread_id[i].cv);
1881                         mutex_destroy(&mpt->m_doneq_thread_id[i].mutex);
1882                 }
1883                 kmem_free(mpt->m_doneq_thread_id,
1884                     sizeof (mptsas_doneq_thread_list_t)
1885                     * doneq_thread_num);
1886                 mutex_exit(&mpt->m_doneq_mutex);
1887                 cv_destroy(&mpt->m_doneq_thread_cv);
1888                 mutex_destroy(&mpt->m_doneq_mutex);
1889         }
1890 
1891         scsi_hba_reset_notify_tear_down(mpt->m_reset_notify_listf);
1892 
1893         mptsas_list_del(mpt);
1894 
1895         /*
1896          * Cancel timeout threads for this mpt
1897          */
1898         mutex_enter(&mpt->m_mutex);
1899         if (mpt->m_quiesce_timeid) {
1900                 timeout_id_t tid = mpt->m_quiesce_timeid;
1901                 mpt->m_quiesce_timeid = 0;
1902                 mutex_exit(&mpt->m_mutex);
1903                 (void) untimeout(tid);
1904                 mutex_enter(&mpt->m_mutex);
1905         }
1906 
1907         if (mpt->m_restart_cmd_timeid) {
1908                 timeout_id_t tid = mpt->m_restart_cmd_timeid;
1909                 mpt->m_restart_cmd_timeid = 0;
1910                 mutex_exit(&mpt->m_mutex);
1911                 (void) untimeout(tid);
1912                 mutex_enter(&mpt->m_mutex);
1913         }
1914 
1915         mutex_exit(&mpt->m_mutex);
1916 
1917         /*
1918          * last mpt? ... if active, CANCEL watch threads.
1919          */
1920         mutex_enter(&mptsas_global_mutex);
1921         if (mptsas_head == NULL) {
1922                 timeout_id_t tid;
1923                 /*
1924                  * Clear mptsas_timeouts_enable so that the watch thread
1925                  * gets restarted on DDI_ATTACH
1926                  */
1927                 mptsas_timeouts_enabled = 0;
1928                 if (mptsas_timeout_id) {
1929                         tid = mptsas_timeout_id;
1930                         mptsas_timeout_id = 0;
1931                         mutex_exit(&mptsas_global_mutex);
1932                         (void) untimeout(tid);
1933                         mutex_enter(&mptsas_global_mutex);
1934                 }
1935                 if (mptsas_reset_watch) {
1936                         tid = mptsas_reset_watch;
1937                         mptsas_reset_watch = 0;
1938                         mutex_exit(&mptsas_global_mutex);
1939                         (void) untimeout(tid);
1940                         mutex_enter(&mptsas_global_mutex);
1941                 }
1942         }
1943         mutex_exit(&mptsas_global_mutex);
1944 
1945         /*
1946          * Delete Phy stats
1947          */
1948         mptsas_destroy_phy_stats(mpt);
1949 
1950         mptsas_destroy_hashes(mpt);
1951 
1952         /*
1953          * Delete nt_active.
1954          */
1955         mutex_enter(&mpt->m_mutex);
1956         mptsas_free_active_slots(mpt);
1957         mutex_exit(&mpt->m_mutex);
1958 
1959         /* deallocate everything that was allocated in mptsas_attach */
1960         mptsas_cache_destroy(mpt);
1961 
1962         mptsas_hba_fini(mpt);
1963         mptsas_cfg_fini(mpt);
1964 
1965         /* Lower the power informing PM Framework */
1966         if (mpt->m_options & MPTSAS_OPT_PM) {
1967                 if (pm_lower_power(dip, 0, PM_LEVEL_D3) != DDI_SUCCESS)
1968                         mptsas_log(mpt, CE_WARN,
1969                             "!mptsas%d: Lower power request failed "
1970                             "during detach, ignoring.",
1971                             mpt->m_instance);
1972         }
1973 
1974         mutex_destroy(&mpt->m_tx_waitq_mutex);
1975         mutex_destroy(&mpt->m_passthru_mutex);
1976         mutex_destroy(&mpt->m_mutex);
1977         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1978                 mutex_destroy(&mpt->m_phy_info[i].smhba_info.phy_mutex);
1979         }
1980         cv_destroy(&mpt->m_cv);
1981         cv_destroy(&mpt->m_passthru_cv);
1982         cv_destroy(&mpt->m_fw_cv);
1983         cv_destroy(&mpt->m_config_cv);
1984         cv_destroy(&mpt->m_fw_diag_cv);
1985 
1986 
1987         mptsas_smp_teardown(mpt);
1988         mptsas_hba_teardown(mpt);
1989 
1990         mptsas_config_space_fini(mpt);
1991 
1992         mptsas_free_handshake_msg(mpt);
1993 
1994         mptsas_fm_fini(mpt);
1995         ddi_soft_state_free(mptsas_state, ddi_get_instance(dip));
1996         ddi_prop_remove_all(dip);
1997 
1998         return (DDI_SUCCESS);
1999 }
2000 
2001 static void
2002 mptsas_list_add(mptsas_t *mpt)
2003 {
2004         rw_enter(&mptsas_global_rwlock, RW_WRITER);
2005 
2006         if (mptsas_head == NULL) {
2007                 mptsas_head = mpt;
2008         } else {
2009                 mptsas_tail->m_next = mpt;
2010         }
2011         mptsas_tail = mpt;
2012         rw_exit(&mptsas_global_rwlock);
2013 }
2014 
2015 static void
2016 mptsas_list_del(mptsas_t *mpt)
2017 {
2018         mptsas_t *m;
2019         /*
2020          * Remove device instance from the global linked list
2021          */
2022         rw_enter(&mptsas_global_rwlock, RW_WRITER);
2023         if (mptsas_head == mpt) {
2024                 m = mptsas_head = mpt->m_next;
2025         } else {
2026                 for (m = mptsas_head; m != NULL; m = m->m_next) {
2027                         if (m->m_next == mpt) {
2028                                 m->m_next = mpt->m_next;
2029                                 break;
2030                         }
2031                 }
2032                 if (m == NULL) {
2033                         mptsas_log(mpt, CE_PANIC, "Not in softc list!");
2034                 }
2035         }
2036 
2037         if (mptsas_tail == mpt) {
2038                 mptsas_tail = m;
2039         }
2040         rw_exit(&mptsas_global_rwlock);
2041 }
2042 
2043 static int
2044 mptsas_alloc_handshake_msg(mptsas_t *mpt, size_t alloc_size)
2045 {
2046         ddi_dma_attr_t  task_dma_attrs;
2047 
2048         mpt->m_hshk_dma_size = 0;
2049         task_dma_attrs = mpt->m_msg_dma_attr;
2050         task_dma_attrs.dma_attr_sgllen = 1;
2051         task_dma_attrs.dma_attr_granular = (uint32_t)(alloc_size);
2052 
2053         /* allocate Task Management ddi_dma resources */
2054         if (mptsas_dma_addr_create(mpt, task_dma_attrs,
2055             &mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl, &mpt->m_hshk_memp,
2056             alloc_size, NULL) == FALSE) {
2057                 return (DDI_FAILURE);
2058         }
2059         mpt->m_hshk_dma_size = alloc_size;
2060 
2061         return (DDI_SUCCESS);
2062 }
2063 
2064 static void
2065 mptsas_free_handshake_msg(mptsas_t *mpt)
2066 {
2067         if (mpt->m_hshk_dma_size == 0)
2068                 return;
2069         mptsas_dma_addr_destroy(&mpt->m_hshk_dma_hdl, &mpt->m_hshk_acc_hdl);
2070         mpt->m_hshk_dma_size = 0;
2071 }
2072 
2073 static int
2074 mptsas_hba_setup(mptsas_t *mpt)
2075 {
2076         scsi_hba_tran_t         *hba_tran;
2077         int                     tran_flags;
2078 
2079         /* Allocate a transport structure */
2080         hba_tran = mpt->m_tran = scsi_hba_tran_alloc(mpt->m_dip,
2081             SCSI_HBA_CANSLEEP);
2082         ASSERT(mpt->m_tran != NULL);
2083 
2084         hba_tran->tran_hba_private   = mpt;
2085         hba_tran->tran_tgt_private   = NULL;
2086 
2087         hba_tran->tran_tgt_init              = mptsas_scsi_tgt_init;
2088         hba_tran->tran_tgt_free              = mptsas_scsi_tgt_free;
2089 
2090         hba_tran->tran_start         = mptsas_scsi_start;
2091         hba_tran->tran_reset         = mptsas_scsi_reset;
2092         hba_tran->tran_abort         = mptsas_scsi_abort;
2093         hba_tran->tran_getcap                = mptsas_scsi_getcap;
2094         hba_tran->tran_setcap                = mptsas_scsi_setcap;
2095         hba_tran->tran_init_pkt              = mptsas_scsi_init_pkt;
2096         hba_tran->tran_destroy_pkt   = mptsas_scsi_destroy_pkt;
2097 
2098         hba_tran->tran_dmafree               = mptsas_scsi_dmafree;
2099         hba_tran->tran_sync_pkt              = mptsas_scsi_sync_pkt;
2100         hba_tran->tran_reset_notify  = mptsas_scsi_reset_notify;
2101 
2102         hba_tran->tran_get_bus_addr  = mptsas_get_bus_addr;
2103         hba_tran->tran_get_name              = mptsas_get_name;
2104 
2105         hba_tran->tran_quiesce               = mptsas_scsi_quiesce;
2106         hba_tran->tran_unquiesce     = mptsas_scsi_unquiesce;
2107         hba_tran->tran_bus_reset     = NULL;
2108 
2109         hba_tran->tran_add_eventcall = NULL;
2110         hba_tran->tran_get_eventcookie       = NULL;
2111         hba_tran->tran_post_event    = NULL;
2112         hba_tran->tran_remove_eventcall      = NULL;
2113 
2114         hba_tran->tran_bus_config    = mptsas_bus_config;
2115 
2116         hba_tran->tran_interconnect_type = INTERCONNECT_SAS;
2117 
2118         /*
2119          * All children of the HBA are iports. We need tran was cloned.
2120          * So we pass the flags to SCSA. SCSI_HBA_TRAN_CLONE will be
2121          * inherited to iport's tran vector.
2122          */
2123         tran_flags = (SCSI_HBA_HBA | SCSI_HBA_TRAN_CLONE);
2124 
2125         if (scsi_hba_attach_setup(mpt->m_dip, &mpt->m_msg_dma_attr,
2126             hba_tran, tran_flags) != DDI_SUCCESS) {
2127                 mptsas_log(mpt, CE_WARN, "hba attach setup failed");
2128                 scsi_hba_tran_free(hba_tran);
2129                 mpt->m_tran = NULL;
2130                 return (FALSE);
2131         }
2132         return (TRUE);
2133 }
2134 
2135 static void
2136 mptsas_hba_teardown(mptsas_t *mpt)
2137 {
2138         (void) scsi_hba_detach(mpt->m_dip);
2139         if (mpt->m_tran != NULL) {
2140                 scsi_hba_tran_free(mpt->m_tran);
2141                 mpt->m_tran = NULL;
2142         }
2143 }
2144 
2145 static void
2146 mptsas_iport_register(mptsas_t *mpt)
2147 {
2148         int i, j;
2149         mptsas_phymask_t        mask = 0x0;
2150         /*
2151          * initial value of mask is 0
2152          */
2153         mutex_enter(&mpt->m_mutex);
2154         for (i = 0; i < mpt->m_num_phys; i++) {
2155                 mptsas_phymask_t phy_mask = 0x0;
2156                 char phy_mask_name[MPTSAS_MAX_PHYS];
2157                 uint8_t current_port;
2158 
2159                 if (mpt->m_phy_info[i].attached_devhdl == 0)
2160                         continue;
2161 
2162                 bzero(phy_mask_name, sizeof (phy_mask_name));
2163 
2164                 current_port = mpt->m_phy_info[i].port_num;
2165 
2166                 if ((mask & (1 << i)) != 0)
2167                         continue;
2168 
2169                 for (j = 0; j < mpt->m_num_phys; j++) {
2170                         if (mpt->m_phy_info[j].attached_devhdl &&
2171                             (mpt->m_phy_info[j].port_num == current_port)) {
2172                                 phy_mask |= (1 << j);
2173                         }
2174                 }
2175                 mask = mask | phy_mask;
2176 
2177                 for (j = 0; j < mpt->m_num_phys; j++) {
2178                         if ((phy_mask >> j) & 0x01) {
2179                                 mpt->m_phy_info[j].phy_mask = phy_mask;
2180                         }
2181                 }
2182 
2183                 (void) sprintf(phy_mask_name, "%x", phy_mask);
2184 
2185                 mutex_exit(&mpt->m_mutex);
2186                 /*
2187                  * register a iport
2188                  */
2189                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
2190                 mutex_enter(&mpt->m_mutex);
2191         }
2192         mutex_exit(&mpt->m_mutex);
2193         /*
2194          * register a virtual port for RAID volume always
2195          */
2196         (void) scsi_hba_iport_register(mpt->m_dip, "v0");
2197 
2198 }
2199 
2200 static int
2201 mptsas_smp_setup(mptsas_t *mpt)
2202 {
2203         mpt->m_smptran = smp_hba_tran_alloc(mpt->m_dip);
2204         ASSERT(mpt->m_smptran != NULL);
2205         mpt->m_smptran->smp_tran_hba_private = mpt;
2206         mpt->m_smptran->smp_tran_start = mptsas_smp_start;
2207         if (smp_hba_attach_setup(mpt->m_dip, mpt->m_smptran) != DDI_SUCCESS) {
2208                 mptsas_log(mpt, CE_WARN, "smp attach setup failed");
2209                 smp_hba_tran_free(mpt->m_smptran);
2210                 mpt->m_smptran = NULL;
2211                 return (FALSE);
2212         }
2213         /*
2214          * Initialize smp hash table
2215          */
2216         mpt->m_smp_targets = refhash_create(MPTSAS_SMP_BUCKET_COUNT,
2217             mptsas_target_addr_hash, mptsas_target_addr_cmp,
2218             mptsas_smp_free, sizeof (mptsas_smp_t),
2219             offsetof(mptsas_smp_t, m_link), offsetof(mptsas_smp_t, m_addr),
2220             KM_SLEEP);
2221         mpt->m_smp_devhdl = 0xFFFF;
2222 
2223         return (TRUE);
2224 }
2225 
2226 static void
2227 mptsas_smp_teardown(mptsas_t *mpt)
2228 {
2229         (void) smp_hba_detach(mpt->m_dip);
2230         if (mpt->m_smptran != NULL) {
2231                 smp_hba_tran_free(mpt->m_smptran);
2232                 mpt->m_smptran = NULL;
2233         }
2234         mpt->m_smp_devhdl = 0;
2235 }
2236 
2237 static int
2238 mptsas_cache_create(mptsas_t *mpt)
2239 {
2240         int instance = mpt->m_instance;
2241         char buf[64];
2242 
2243         /*
2244          * create kmem cache for packets
2245          */
2246         (void) sprintf(buf, "mptsas%d_cache", instance);
2247         mpt->m_kmem_cache = kmem_cache_create(buf,
2248             sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
2249             mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2250             NULL, (void *)mpt, NULL, 0);
2251 
2252         if (mpt->m_kmem_cache == NULL) {
2253                 mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2254                 return (FALSE);
2255         }
2256 
2257         /*
2258          * create kmem cache for extra SGL frames if SGL cannot
2259          * be accomodated into main request frame.
2260          */
2261         (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2262         mpt->m_cache_frames = kmem_cache_create(buf,
2263             sizeof (mptsas_cache_frames_t), 8,
2264             mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2265             NULL, (void *)mpt, NULL, 0);
2266 
2267         if (mpt->m_cache_frames == NULL) {
2268                 mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2269                 return (FALSE);
2270         }
2271 
2272         return (TRUE);
2273 }
2274 
2275 static void
2276 mptsas_cache_destroy(mptsas_t *mpt)
2277 {
2278         /* deallocate in reverse order */
2279         if (mpt->m_cache_frames) {
2280                 kmem_cache_destroy(mpt->m_cache_frames);
2281                 mpt->m_cache_frames = NULL;
2282         }
2283         if (mpt->m_kmem_cache) {
2284                 kmem_cache_destroy(mpt->m_kmem_cache);
2285                 mpt->m_kmem_cache = NULL;
2286         }
2287 }
2288 
2289 static int
2290 mptsas_power(dev_info_t *dip, int component, int level)
2291 {
2292 #ifndef __lock_lint
2293         _NOTE(ARGUNUSED(component))
2294 #endif
2295         mptsas_t        *mpt;
2296         int             rval = DDI_SUCCESS;
2297         int             polls = 0;
2298         uint32_t        ioc_status;
2299 
2300         if (scsi_hba_iport_unit_address(dip) != 0)
2301                 return (DDI_SUCCESS);
2302 
2303         mpt = ddi_get_soft_state(mptsas_state, ddi_get_instance(dip));
2304         if (mpt == NULL) {
2305                 return (DDI_FAILURE);
2306         }
2307 
2308         mutex_enter(&mpt->m_mutex);
2309 
2310         /*
2311          * If the device is busy, don't lower its power level
2312          */
2313         if (mpt->m_busy && (mpt->m_power_level > level)) {
2314                 mutex_exit(&mpt->m_mutex);
2315                 return (DDI_FAILURE);
2316         }
2317         switch (level) {
2318         case PM_LEVEL_D0:
2319                 NDBG11(("mptsas%d: turning power ON.", mpt->m_instance));
2320                 MPTSAS_POWER_ON(mpt);
2321                 /*
2322                  * Wait up to 30 seconds for IOC to come out of reset.
2323                  */
2324                 while (((ioc_status = ddi_get32(mpt->m_datap,
2325                     &mpt->m_reg->Doorbell)) &
2326                     MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) {
2327                         if (polls++ > 3000) {
2328                                 break;
2329                         }
2330                         delay(drv_usectohz(10000));
2331                 }
2332                 /*
2333                  * If IOC is not in operational state, try to hard reset it.
2334                  */
2335                 if ((ioc_status & MPI2_IOC_STATE_MASK) !=
2336                     MPI2_IOC_STATE_OPERATIONAL) {
2337                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
2338                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
2339                                 mptsas_log(mpt, CE_WARN,
2340                                     "mptsas_power: hard reset failed");
2341                                 mutex_exit(&mpt->m_mutex);
2342                                 return (DDI_FAILURE);
2343                         }
2344                 }
2345                 mpt->m_power_level = PM_LEVEL_D0;
2346                 break;
2347         case PM_LEVEL_D3:
2348                 NDBG11(("mptsas%d: turning power OFF.", mpt->m_instance));
2349                 MPTSAS_POWER_OFF(mpt);
2350                 break;
2351         default:
2352                 mptsas_log(mpt, CE_WARN, "mptsas%d: unknown power level <%x>.",
2353                     mpt->m_instance, level);
2354                 rval = DDI_FAILURE;
2355                 break;
2356         }
2357         mutex_exit(&mpt->m_mutex);
2358         return (rval);
2359 }
2360 
2361 /*
2362  * Initialize configuration space and figure out which
2363  * chip and revison of the chip the mpt driver is using.
2364  */
2365 static int
2366 mptsas_config_space_init(mptsas_t *mpt)
2367 {
2368         NDBG0(("mptsas_config_space_init"));
2369 
2370         if (mpt->m_config_handle != NULL)
2371                 return (TRUE);
2372 
2373         if (pci_config_setup(mpt->m_dip,
2374             &mpt->m_config_handle) != DDI_SUCCESS) {
2375                 mptsas_log(mpt, CE_WARN, "cannot map configuration space.");
2376                 return (FALSE);
2377         }
2378 
2379         /*
2380          * This is a workaround for a XMITS ASIC bug which does not
2381          * drive the CBE upper bits.
2382          */
2383         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT) &
2384             PCI_STAT_PERROR) {
2385                 pci_config_put16(mpt->m_config_handle, PCI_CONF_STAT,
2386                     PCI_STAT_PERROR);
2387         }
2388 
2389         mptsas_setup_cmd_reg(mpt);
2390 
2391         /*
2392          * Get the chip device id:
2393          */
2394         mpt->m_devid = pci_config_get16(mpt->m_config_handle, PCI_CONF_DEVID);
2395 
2396         /*
2397          * Save the revision.
2398          */
2399         mpt->m_revid = pci_config_get8(mpt->m_config_handle, PCI_CONF_REVID);
2400 
2401         /*
2402          * Save the SubSystem Vendor and Device IDs
2403          */
2404         mpt->m_svid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBVENID);
2405         mpt->m_ssid = pci_config_get16(mpt->m_config_handle, PCI_CONF_SUBSYSID);
2406 
2407         /*
2408          * Set the latency timer to 0x40 as specified by the upa -> pci
2409          * bridge chip design team.  This may be done by the sparc pci
2410          * bus nexus driver, but the driver should make sure the latency
2411          * timer is correct for performance reasons.
2412          */
2413         pci_config_put8(mpt->m_config_handle, PCI_CONF_LATENCY_TIMER,
2414             MPTSAS_LATENCY_TIMER);
2415 
2416         (void) mptsas_get_pci_cap(mpt);
2417         return (TRUE);
2418 }
2419 
2420 static void
2421 mptsas_config_space_fini(mptsas_t *mpt)
2422 {
2423         if (mpt->m_config_handle != NULL) {
2424                 mptsas_disable_bus_master(mpt);
2425                 pci_config_teardown(&mpt->m_config_handle);
2426                 mpt->m_config_handle = NULL;
2427         }
2428 }
2429 
2430 static void
2431 mptsas_setup_cmd_reg(mptsas_t *mpt)
2432 {
2433         ushort_t        cmdreg;
2434 
2435         /*
2436          * Set the command register to the needed values.
2437          */
2438         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2439         cmdreg |= (PCI_COMM_ME | PCI_COMM_SERR_ENABLE |
2440             PCI_COMM_PARITY_DETECT | PCI_COMM_MAE);
2441         cmdreg &= ~PCI_COMM_IO;
2442         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2443 }
2444 
2445 static void
2446 mptsas_disable_bus_master(mptsas_t *mpt)
2447 {
2448         ushort_t        cmdreg;
2449 
2450         /*
2451          * Clear the master enable bit in the PCI command register.
2452          * This prevents any bus mastering activity like DMA.
2453          */
2454         cmdreg = pci_config_get16(mpt->m_config_handle, PCI_CONF_COMM);
2455         cmdreg &= ~PCI_COMM_ME;
2456         pci_config_put16(mpt->m_config_handle, PCI_CONF_COMM, cmdreg);
2457 }
2458 
2459 int
2460 mptsas_dma_alloc(mptsas_t *mpt, mptsas_dma_alloc_state_t *dma_statep)
2461 {
2462         ddi_dma_attr_t  attrs;
2463 
2464         attrs = mpt->m_io_dma_attr;
2465         attrs.dma_attr_sgllen = 1;
2466 
2467         ASSERT(dma_statep != NULL);
2468 
2469         if (mptsas_dma_addr_create(mpt, attrs, &dma_statep->handle,
2470             &dma_statep->accessp, &dma_statep->memp, dma_statep->size,
2471             &dma_statep->cookie) == FALSE) {
2472                 return (DDI_FAILURE);
2473         }
2474 
2475         return (DDI_SUCCESS);
2476 }
2477 
2478 void
2479 mptsas_dma_free(mptsas_dma_alloc_state_t *dma_statep)
2480 {
2481         ASSERT(dma_statep != NULL);
2482         mptsas_dma_addr_destroy(&dma_statep->handle, &dma_statep->accessp);
2483         dma_statep->size = 0;
2484 }
2485 
2486 int
2487 mptsas_do_dma(mptsas_t *mpt, uint32_t size, int var, int (*callback)())
2488 {
2489         ddi_dma_attr_t          attrs;
2490         ddi_dma_handle_t        dma_handle;
2491         caddr_t                 memp;
2492         ddi_acc_handle_t        accessp;
2493         int                     rval;
2494 
2495         ASSERT(mutex_owned(&mpt->m_mutex));
2496 
2497         attrs = mpt->m_msg_dma_attr;
2498         attrs.dma_attr_sgllen = 1;
2499         attrs.dma_attr_granular = size;
2500 
2501         if (mptsas_dma_addr_create(mpt, attrs, &dma_handle,
2502             &accessp, &memp, size, NULL) == FALSE) {
2503                 return (DDI_FAILURE);
2504         }
2505 
2506         rval = (*callback) (mpt, memp, var, accessp);
2507 
2508         if ((mptsas_check_dma_handle(dma_handle) != DDI_SUCCESS) ||
2509             (mptsas_check_acc_handle(accessp) != DDI_SUCCESS)) {
2510                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
2511                 rval = DDI_FAILURE;
2512         }
2513 
2514         mptsas_dma_addr_destroy(&dma_handle, &accessp);
2515         return (rval);
2516 
2517 }
2518 
2519 static int
2520 mptsas_alloc_request_frames(mptsas_t *mpt)
2521 {
2522         ddi_dma_attr_t          frame_dma_attrs;
2523         caddr_t                 memp;
2524         ddi_dma_cookie_t        cookie;
2525         size_t                  mem_size;
2526 
2527         /*
2528          * re-alloc when it has already alloced
2529          */
2530         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2531             &mpt->m_acc_req_frame_hdl);
2532 
2533         /*
2534          * The size of the request frame pool is:
2535          *   Number of Request Frames * Request Frame Size
2536          */
2537         mem_size = mpt->m_max_requests * mpt->m_req_frame_size;
2538 
2539         /*
2540          * set the DMA attributes.  System Request Message Frames must be
2541          * aligned on a 16-byte boundry.
2542          */
2543         frame_dma_attrs = mpt->m_msg_dma_attr;
2544         frame_dma_attrs.dma_attr_align = 16;
2545         frame_dma_attrs.dma_attr_sgllen = 1;
2546 
2547         /*
2548          * allocate the request frame pool.
2549          */
2550         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2551             &mpt->m_dma_req_frame_hdl, &mpt->m_acc_req_frame_hdl, &memp,
2552             mem_size, &cookie) == FALSE) {
2553                 return (DDI_FAILURE);
2554         }
2555 
2556         /*
2557          * Store the request frame memory address.  This chip uses this
2558          * address to dma to and from the driver's frame.  The second
2559          * address is the address mpt uses to fill in the frame.
2560          */
2561         mpt->m_req_frame_dma_addr = cookie.dmac_laddress;
2562         mpt->m_req_frame = memp;
2563 
2564         /*
2565          * Clear the request frame pool.
2566          */
2567         bzero(mpt->m_req_frame, mem_size);
2568 
2569         return (DDI_SUCCESS);
2570 }
2571 
2572 static int
2573 mptsas_alloc_reply_frames(mptsas_t *mpt)
2574 {
2575         ddi_dma_attr_t          frame_dma_attrs;
2576         caddr_t                 memp;
2577         ddi_dma_cookie_t        cookie;
2578         size_t                  mem_size;
2579 
2580         /*
2581          * re-alloc when it has already alloced
2582          */
2583         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2584             &mpt->m_acc_reply_frame_hdl);
2585 
2586         /*
2587          * The size of the reply frame pool is:
2588          *   Number of Reply Frames * Reply Frame Size
2589          */
2590         mem_size = mpt->m_max_replies * mpt->m_reply_frame_size;
2591 
2592         /*
2593          * set the DMA attributes.   System Reply Message Frames must be
2594          * aligned on a 4-byte boundry.  This is the default.
2595          */
2596         frame_dma_attrs = mpt->m_msg_dma_attr;
2597         frame_dma_attrs.dma_attr_sgllen = 1;
2598 
2599         /*
2600          * allocate the reply frame pool
2601          */
2602         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2603             &mpt->m_dma_reply_frame_hdl, &mpt->m_acc_reply_frame_hdl, &memp,
2604             mem_size, &cookie) == FALSE) {
2605                 return (DDI_FAILURE);
2606         }
2607 
2608         /*
2609          * Store the reply frame memory address.  This chip uses this
2610          * address to dma to and from the driver's frame.  The second
2611          * address is the address mpt uses to process the frame.
2612          */
2613         mpt->m_reply_frame_dma_addr = cookie.dmac_laddress;
2614         mpt->m_reply_frame = memp;
2615 
2616         /*
2617          * Clear the reply frame pool.
2618          */
2619         bzero(mpt->m_reply_frame, mem_size);
2620 
2621         return (DDI_SUCCESS);
2622 }
2623 
2624 static int
2625 mptsas_alloc_free_queue(mptsas_t *mpt)
2626 {
2627         ddi_dma_attr_t          frame_dma_attrs;
2628         caddr_t                 memp;
2629         ddi_dma_cookie_t        cookie;
2630         size_t                  mem_size;
2631 
2632         /*
2633          * re-alloc when it has already alloced
2634          */
2635         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2636             &mpt->m_acc_free_queue_hdl);
2637 
2638         /*
2639          * The reply free queue size is:
2640          *   Reply Free Queue Depth * 4
2641          * The "4" is the size of one 32 bit address (low part of 64-bit
2642          *   address)
2643          */
2644         mem_size = mpt->m_free_queue_depth * 4;
2645 
2646         /*
2647          * set the DMA attributes  The Reply Free Queue must be aligned on a
2648          * 16-byte boundry.
2649          */
2650         frame_dma_attrs = mpt->m_msg_dma_attr;
2651         frame_dma_attrs.dma_attr_align = 16;
2652         frame_dma_attrs.dma_attr_sgllen = 1;
2653 
2654         /*
2655          * allocate the reply free queue
2656          */
2657         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2658             &mpt->m_dma_free_queue_hdl, &mpt->m_acc_free_queue_hdl, &memp,
2659             mem_size, &cookie) == FALSE) {
2660                 return (DDI_FAILURE);
2661         }
2662 
2663         /*
2664          * Store the reply free queue memory address.  This chip uses this
2665          * address to read from the reply free queue.  The second address
2666          * is the address mpt uses to manage the queue.
2667          */
2668         mpt->m_free_queue_dma_addr = cookie.dmac_laddress;
2669         mpt->m_free_queue = memp;
2670 
2671         /*
2672          * Clear the reply free queue memory.
2673          */
2674         bzero(mpt->m_free_queue, mem_size);
2675 
2676         return (DDI_SUCCESS);
2677 }
2678 
2679 static int
2680 mptsas_alloc_post_queue(mptsas_t *mpt)
2681 {
2682         ddi_dma_attr_t          frame_dma_attrs;
2683         caddr_t                 memp;
2684         ddi_dma_cookie_t        cookie;
2685         size_t                  mem_size;
2686 
2687         /*
2688          * re-alloc when it has already alloced
2689          */
2690         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2691             &mpt->m_acc_post_queue_hdl);
2692 
2693         /*
2694          * The reply descriptor post queue size is:
2695          *   Reply Descriptor Post Queue Depth * 8
2696          * The "8" is the size of each descriptor (8 bytes or 64 bits).
2697          */
2698         mem_size = mpt->m_post_queue_depth * 8;
2699 
2700         /*
2701          * set the DMA attributes.  The Reply Descriptor Post Queue must be
2702          * aligned on a 16-byte boundry.
2703          */
2704         frame_dma_attrs = mpt->m_msg_dma_attr;
2705         frame_dma_attrs.dma_attr_align = 16;
2706         frame_dma_attrs.dma_attr_sgllen = 1;
2707 
2708         /*
2709          * allocate the reply post queue
2710          */
2711         if (mptsas_dma_addr_create(mpt, frame_dma_attrs,
2712             &mpt->m_dma_post_queue_hdl, &mpt->m_acc_post_queue_hdl, &memp,
2713             mem_size, &cookie) == FALSE) {
2714                 return (DDI_FAILURE);
2715         }
2716 
2717         /*
2718          * Store the reply descriptor post queue memory address.  This chip
2719          * uses this address to write to the reply descriptor post queue.  The
2720          * second address is the address mpt uses to manage the queue.
2721          */
2722         mpt->m_post_queue_dma_addr = cookie.dmac_laddress;
2723         mpt->m_post_queue = memp;
2724 
2725         /*
2726          * Clear the reply post queue memory.
2727          */
2728         bzero(mpt->m_post_queue, mem_size);
2729 
2730         return (DDI_SUCCESS);
2731 }
2732 
2733 static void
2734 mptsas_alloc_reply_args(mptsas_t *mpt)
2735 {
2736         if (mpt->m_replyh_args == NULL) {
2737                 mpt->m_replyh_args = kmem_zalloc(sizeof (m_replyh_arg_t) *
2738                     mpt->m_max_replies, KM_SLEEP);
2739         }
2740 }
2741 
2742 static int
2743 mptsas_alloc_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2744 {
2745         mptsas_cache_frames_t   *frames = NULL;
2746         if (cmd->cmd_extra_frames == NULL) {
2747                 frames = kmem_cache_alloc(mpt->m_cache_frames, KM_NOSLEEP);
2748                 if (frames == NULL) {
2749                         return (DDI_FAILURE);
2750                 }
2751                 cmd->cmd_extra_frames = frames;
2752         }
2753         return (DDI_SUCCESS);
2754 }
2755 
2756 static void
2757 mptsas_free_extra_sgl_frame(mptsas_t *mpt, mptsas_cmd_t *cmd)
2758 {
2759         if (cmd->cmd_extra_frames) {
2760                 kmem_cache_free(mpt->m_cache_frames,
2761                     (void *)cmd->cmd_extra_frames);
2762                 cmd->cmd_extra_frames = NULL;
2763         }
2764 }
2765 
2766 static void
2767 mptsas_cfg_fini(mptsas_t *mpt)
2768 {
2769         NDBG0(("mptsas_cfg_fini"));
2770         ddi_regs_map_free(&mpt->m_datap);
2771 }
2772 
2773 static void
2774 mptsas_hba_fini(mptsas_t *mpt)
2775 {
2776         NDBG0(("mptsas_hba_fini"));
2777 
2778         /*
2779          * Free up any allocated memory
2780          */
2781         mptsas_dma_addr_destroy(&mpt->m_dma_req_frame_hdl,
2782             &mpt->m_acc_req_frame_hdl);
2783 
2784         mptsas_dma_addr_destroy(&mpt->m_dma_reply_frame_hdl,
2785             &mpt->m_acc_reply_frame_hdl);
2786 
2787         mptsas_dma_addr_destroy(&mpt->m_dma_free_queue_hdl,
2788             &mpt->m_acc_free_queue_hdl);
2789 
2790         mptsas_dma_addr_destroy(&mpt->m_dma_post_queue_hdl,
2791             &mpt->m_acc_post_queue_hdl);
2792 
2793         if (mpt->m_replyh_args != NULL) {
2794                 kmem_free(mpt->m_replyh_args, sizeof (m_replyh_arg_t)
2795                     * mpt->m_max_replies);
2796         }
2797 }
2798 
2799 static int
2800 mptsas_name_child(dev_info_t *lun_dip, char *name, int len)
2801 {
2802         int             lun = 0;
2803         char            *sas_wwn = NULL;
2804         int             phynum = -1;
2805         int             reallen = 0;
2806 
2807         /* Get the target num */
2808         lun = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip, DDI_PROP_DONTPASS,
2809             LUN_PROP, 0);
2810 
2811         if ((phynum = ddi_prop_get_int(DDI_DEV_T_ANY, lun_dip,
2812             DDI_PROP_DONTPASS, "sata-phy", -1)) != -1) {
2813                 /*
2814                  * Stick in the address of form "pPHY,LUN"
2815                  */
2816                 reallen = snprintf(name, len, "p%x,%x", phynum, lun);
2817         } else if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip,
2818             DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &sas_wwn)
2819             == DDI_PROP_SUCCESS) {
2820                 /*
2821                  * Stick in the address of the form "wWWN,LUN"
2822                  */
2823                 reallen = snprintf(name, len, "%s,%x", sas_wwn, lun);
2824                 ddi_prop_free(sas_wwn);
2825         } else {
2826                 return (DDI_FAILURE);
2827         }
2828 
2829         ASSERT(reallen < len);
2830         if (reallen >= len) {
2831                 mptsas_log(0, CE_WARN, "!mptsas_get_name: name parameter "
2832                     "length too small, it needs to be %d bytes", reallen + 1);
2833         }
2834         return (DDI_SUCCESS);
2835 }
2836 
2837 /*
2838  * tran_tgt_init(9E) - target device instance initialization
2839  */
2840 static int
2841 mptsas_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
2842     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
2843 {
2844 #ifndef __lock_lint
2845         _NOTE(ARGUNUSED(hba_tran))
2846 #endif
2847 
2848         /*
2849          * At this point, the scsi_device structure already exists
2850          * and has been initialized.
2851          *
2852          * Use this function to allocate target-private data structures,
2853          * if needed by this HBA.  Add revised flow-control and queue
2854          * properties for child here, if desired and if you can tell they
2855          * support tagged queueing by now.
2856          */
2857         mptsas_t                *mpt;
2858         int                     lun = sd->sd_address.a_lun;
2859         mdi_pathinfo_t          *pip = NULL;
2860         mptsas_tgt_private_t    *tgt_private = NULL;
2861         mptsas_target_t         *ptgt = NULL;
2862         char                    *psas_wwn = NULL;
2863         mptsas_phymask_t        phymask = 0;
2864         uint64_t                sas_wwn = 0;
2865         mptsas_target_addr_t    addr;
2866         mpt = SDEV2MPT(sd);
2867 
2868         ASSERT(scsi_hba_iport_unit_address(hba_dip) != 0);
2869 
2870         NDBG0(("mptsas_scsi_tgt_init: hbadip=0x%p tgtdip=0x%p lun=%d",
2871             (void *)hba_dip, (void *)tgt_dip, lun));
2872 
2873         if (ndi_dev_is_persistent_node(tgt_dip) == 0) {
2874                 (void) ndi_merge_node(tgt_dip, mptsas_name_child);
2875                 ddi_set_name_addr(tgt_dip, NULL);
2876                 return (DDI_FAILURE);
2877         }
2878         /*
2879          * phymask is 0 means the virtual port for RAID
2880          */
2881         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, hba_dip, 0,
2882             "phymask", 0);
2883         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2884                 if ((pip = (void *)(sd->sd_private)) == NULL) {
2885                         /*
2886                          * Very bad news if this occurs. Somehow scsi_vhci has
2887                          * lost the pathinfo node for this target.
2888                          */
2889                         return (DDI_NOT_WELL_FORMED);
2890                 }
2891 
2892                 if (mdi_prop_lookup_int(pip, LUN_PROP, &lun) !=
2893                     DDI_PROP_SUCCESS) {
2894                         mptsas_log(mpt, CE_WARN, "Get lun property failed\n");
2895                         return (DDI_FAILURE);
2896                 }
2897 
2898                 if (mdi_prop_lookup_string(pip, SCSI_ADDR_PROP_TARGET_PORT,
2899                     &psas_wwn) == MDI_SUCCESS) {
2900                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2901                                 sas_wwn = 0;
2902                         }
2903                         (void) mdi_prop_free(psas_wwn);
2904                 }
2905         } else {
2906                 lun = ddi_prop_get_int(DDI_DEV_T_ANY, tgt_dip,
2907                     DDI_PROP_DONTPASS, LUN_PROP, 0);
2908                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, tgt_dip,
2909                     DDI_PROP_DONTPASS, SCSI_ADDR_PROP_TARGET_PORT, &psas_wwn) ==
2910                     DDI_PROP_SUCCESS) {
2911                         if (scsi_wwnstr_to_wwn(psas_wwn, &sas_wwn)) {
2912                                 sas_wwn = 0;
2913                         }
2914                         ddi_prop_free(psas_wwn);
2915                 } else {
2916                         sas_wwn = 0;
2917                 }
2918         }
2919 
2920         ASSERT((sas_wwn != 0) || (phymask != 0));
2921         addr.mta_wwn = sas_wwn;
2922         addr.mta_phymask = phymask;
2923         mutex_enter(&mpt->m_mutex);
2924         ptgt = refhash_lookup(mpt->m_targets, &addr);
2925         mutex_exit(&mpt->m_mutex);
2926         if (ptgt == NULL) {
2927                 mptsas_log(mpt, CE_WARN, "!tgt_init: target doesn't exist or "
2928                     "gone already! phymask:%x, saswwn %"PRIx64, phymask,
2929                     sas_wwn);
2930                 return (DDI_FAILURE);
2931         }
2932         if (hba_tran->tran_tgt_private == NULL) {
2933                 tgt_private = kmem_zalloc(sizeof (mptsas_tgt_private_t),
2934                     KM_SLEEP);
2935                 tgt_private->t_lun = lun;
2936                 tgt_private->t_private = ptgt;
2937                 hba_tran->tran_tgt_private = tgt_private;
2938         }
2939 
2940         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
2941                 return (DDI_SUCCESS);
2942         }
2943         mutex_enter(&mpt->m_mutex);
2944 
2945         if (ptgt->m_deviceinfo &
2946             (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
2947             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
2948                 uchar_t *inq89 = NULL;
2949                 int inq89_len = 0x238;
2950                 int reallen = 0;
2951                 int rval = 0;
2952                 struct sata_id *sid = NULL;
2953                 char model[SATA_ID_MODEL_LEN + 1];
2954                 char fw[SATA_ID_FW_LEN + 1];
2955                 char *vid, *pid;
2956                 int i;
2957 
2958                 mutex_exit(&mpt->m_mutex);
2959                 /*
2960                  * According SCSI/ATA Translation -2 (SAT-2) revision 01a
2961                  * chapter 12.4.2 VPD page 89h includes 512 bytes ATA IDENTIFY
2962                  * DEVICE data or ATA IDENTIFY PACKET DEVICE data.
2963                  */
2964                 inq89 = kmem_zalloc(inq89_len, KM_SLEEP);
2965                 rval = mptsas_inquiry(mpt, ptgt, 0, 0x89,
2966                     inq89, inq89_len, &reallen, 1);
2967 
2968                 if (rval != 0) {
2969                         if (inq89 != NULL) {
2970                                 kmem_free(inq89, inq89_len);
2971                         }
2972 
2973                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
2974                             "0x89 for SATA target:%x failed!", ptgt->m_devhdl);
2975                         return (DDI_SUCCESS);
2976                 }
2977                 sid = (void *)(&inq89[60]);
2978 
2979                 swab(sid->ai_model, model, SATA_ID_MODEL_LEN);
2980                 swab(sid->ai_fw, fw, SATA_ID_FW_LEN);
2981 
2982                 model[SATA_ID_MODEL_LEN] = 0;
2983                 fw[SATA_ID_FW_LEN] = 0;
2984 
2985                 /*
2986                  * split model into into vid/pid
2987                  */
2988                 for (i = 0, pid = model; i < SATA_ID_MODEL_LEN; i++, pid++)
2989                         if ((*pid == ' ') || (*pid == '\t'))
2990                                 break;
2991                 if (i < SATA_ID_MODEL_LEN) {
2992                         vid = model;
2993                         /*
2994                          * terminate vid, establish pid
2995                          */
2996                         *pid++ = 0;
2997                 } else {
2998                         /*
2999                          * vid will stay "ATA     ", the rule is same
3000                          * as sata framework implementation.
3001                          */
3002                         vid = NULL;
3003                         /*
3004                          * model is all pid
3005                          */
3006                         pid = model;
3007                 }
3008 
3009                 /*
3010                  * override SCSA "inquiry-*" properties
3011                  */
3012                 if (vid)
3013                         (void) scsi_device_prop_update_inqstring(sd,
3014                             INQUIRY_VENDOR_ID, vid, strlen(vid));
3015                 if (pid)
3016                         (void) scsi_device_prop_update_inqstring(sd,
3017                             INQUIRY_PRODUCT_ID, pid, strlen(pid));
3018                 (void) scsi_device_prop_update_inqstring(sd,
3019                     INQUIRY_REVISION_ID, fw, strlen(fw));
3020 
3021                 if (inq89 != NULL) {
3022                         kmem_free(inq89, inq89_len);
3023                 }
3024         } else {
3025                 mutex_exit(&mpt->m_mutex);
3026         }
3027 
3028         return (DDI_SUCCESS);
3029 }
3030 /*
3031  * tran_tgt_free(9E) - target device instance deallocation
3032  */
3033 static void
3034 mptsas_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
3035     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
3036 {
3037 #ifndef __lock_lint
3038         _NOTE(ARGUNUSED(hba_dip, tgt_dip, hba_tran, sd))
3039 #endif
3040 
3041         mptsas_tgt_private_t    *tgt_private = hba_tran->tran_tgt_private;
3042 
3043         if (tgt_private != NULL) {
3044                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
3045                 hba_tran->tran_tgt_private = NULL;
3046         }
3047 }
3048 
3049 /*
3050  * scsi_pkt handling
3051  *
3052  * Visible to the external world via the transport structure.
3053  */
3054 
3055 /*
3056  * Notes:
3057  *      - transport the command to the addressed SCSI target/lun device
3058  *      - normal operation is to schedule the command to be transported,
3059  *        and return TRAN_ACCEPT if this is successful.
3060  *      - if NO_INTR, tran_start must poll device for command completion
3061  */
3062 static int
3063 mptsas_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
3064 {
3065 #ifndef __lock_lint
3066         _NOTE(ARGUNUSED(ap))
3067 #endif
3068         mptsas_t        *mpt = PKT2MPT(pkt);
3069         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3070         int             rval;
3071         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3072 
3073         NDBG1(("mptsas_scsi_start: pkt=0x%p", (void *)pkt));
3074         ASSERT(ptgt);
3075         if (ptgt == NULL)
3076                 return (TRAN_FATAL_ERROR);
3077 
3078         /*
3079          * prepare the pkt before taking mutex.
3080          */
3081         rval = mptsas_prepare_pkt(cmd);
3082         if (rval != TRAN_ACCEPT) {
3083                 return (rval);
3084         }
3085 
3086         /*
3087          * Send the command to target/lun, however your HBA requires it.
3088          * If busy, return TRAN_BUSY; if there's some other formatting error
3089          * in the packet, return TRAN_BADPKT; otherwise, fall through to the
3090          * return of TRAN_ACCEPT.
3091          *
3092          * Remember that access to shared resources, including the mptsas_t
3093          * data structure and the HBA hardware registers, must be protected
3094          * with mutexes, here and everywhere.
3095          *
3096          * Also remember that at interrupt time, you'll get an argument
3097          * to the interrupt handler which is a pointer to your mptsas_t
3098          * structure; you'll have to remember which commands are outstanding
3099          * and which scsi_pkt is the currently-running command so the
3100          * interrupt handler can refer to the pkt to set completion
3101          * status, call the target driver back through pkt_comp, etc.
3102          *
3103          * If the instance lock is held by other thread, don't spin to wait
3104          * for it. Instead, queue the cmd and next time when the instance lock
3105          * is not held, accept all the queued cmd. A extra tx_waitq is
3106          * introduced to protect the queue.
3107          *
3108          * The polled cmd will not be queud and accepted as usual.
3109          *
3110          * Under the tx_waitq mutex, record whether a thread is draining
3111          * the tx_waitq.  An IO requesting thread that finds the instance
3112          * mutex contended appends to the tx_waitq and while holding the
3113          * tx_wait mutex, if the draining flag is not set, sets it and then
3114          * proceeds to spin for the instance mutex. This scheme ensures that
3115          * the last cmd in a burst be processed.
3116          *
3117          * we enable this feature only when the helper threads are enabled,
3118          * at which we think the loads are heavy.
3119          *
3120          * per instance mutex m_tx_waitq_mutex is introduced to protect the
3121          * m_tx_waitqtail, m_tx_waitq, m_tx_draining.
3122          */
3123 
3124         if (mpt->m_doneq_thread_n) {
3125                 if (mutex_tryenter(&mpt->m_mutex) != 0) {
3126                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3127                         mutex_exit(&mpt->m_mutex);
3128                 } else if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3129                         mutex_enter(&mpt->m_mutex);
3130                         rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3131                         mutex_exit(&mpt->m_mutex);
3132                 } else {
3133                         mutex_enter(&mpt->m_tx_waitq_mutex);
3134                         /*
3135                          * ptgt->m_dr_flag is protected by m_mutex or
3136                          * m_tx_waitq_mutex. In this case, m_tx_waitq_mutex
3137                          * is acquired.
3138                          */
3139                         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3140                                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3141                                         /*
3142                                          * The command should be allowed to
3143                                          * retry by returning TRAN_BUSY to
3144                                          * to stall the I/O's which come from
3145                                          * scsi_vhci since the device/path is
3146                                          * in unstable state now.
3147                                          */
3148                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3149                                         return (TRAN_BUSY);
3150                                 } else {
3151                                         /*
3152                                          * The device is offline, just fail the
3153                                          * command by returning
3154                                          * TRAN_FATAL_ERROR.
3155                                          */
3156                                         mutex_exit(&mpt->m_tx_waitq_mutex);
3157                                         return (TRAN_FATAL_ERROR);
3158                                 }
3159                         }
3160                         if (mpt->m_tx_draining) {
3161                                 cmd->cmd_flags |= CFLAG_TXQ;
3162                                 *mpt->m_tx_waitqtail = cmd;
3163                                 mpt->m_tx_waitqtail = &cmd->cmd_linkp;
3164                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3165                         } else { /* drain the queue */
3166                                 mpt->m_tx_draining = 1;
3167                                 mutex_exit(&mpt->m_tx_waitq_mutex);
3168                                 mutex_enter(&mpt->m_mutex);
3169                                 rval = mptsas_accept_txwq_and_pkt(mpt, cmd);
3170                                 mutex_exit(&mpt->m_mutex);
3171                         }
3172                 }
3173         } else {
3174                 mutex_enter(&mpt->m_mutex);
3175                 /*
3176                  * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3177                  * in this case, m_mutex is acquired.
3178                  */
3179                 if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3180                         if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3181                                 /*
3182                                  * commands should be allowed to retry by
3183                                  * returning TRAN_BUSY to stall the I/O's
3184                                  * which come from scsi_vhci since the device/
3185                                  * path is in unstable state now.
3186                                  */
3187                                 mutex_exit(&mpt->m_mutex);
3188                                 return (TRAN_BUSY);
3189                         } else {
3190                                 /*
3191                                  * The device is offline, just fail the
3192                                  * command by returning TRAN_FATAL_ERROR.
3193                                  */
3194                                 mutex_exit(&mpt->m_mutex);
3195                                 return (TRAN_FATAL_ERROR);
3196                         }
3197                 }
3198                 rval = mptsas_accept_pkt(mpt, cmd);
3199                 mutex_exit(&mpt->m_mutex);
3200         }
3201 
3202         return (rval);
3203 }
3204 
3205 /*
3206  * Accept all the queued cmds(if any) before accept the current one.
3207  */
3208 static int
3209 mptsas_accept_txwq_and_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3210 {
3211         int rval;
3212         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3213 
3214         ASSERT(mutex_owned(&mpt->m_mutex));
3215         /*
3216          * The call to mptsas_accept_tx_waitq() must always be performed
3217          * because that is where mpt->m_tx_draining is cleared.
3218          */
3219         mutex_enter(&mpt->m_tx_waitq_mutex);
3220         mptsas_accept_tx_waitq(mpt);
3221         mutex_exit(&mpt->m_tx_waitq_mutex);
3222         /*
3223          * ptgt->m_dr_flag is protected by m_mutex or m_tx_waitq_mutex
3224          * in this case, m_mutex is acquired.
3225          */
3226         if (ptgt->m_dr_flag == MPTSAS_DR_INTRANSITION) {
3227                 if (cmd->cmd_pkt_flags & FLAG_NOQUEUE) {
3228                         /*
3229                          * The command should be allowed to retry by returning
3230                          * TRAN_BUSY to stall the I/O's which come from
3231                          * scsi_vhci since the device/path is in unstable state
3232                          * now.
3233                          */
3234                         return (TRAN_BUSY);
3235                 } else {
3236                         /*
3237                          * The device is offline, just fail the command by
3238                          * return TRAN_FATAL_ERROR.
3239                          */
3240                         return (TRAN_FATAL_ERROR);
3241                 }
3242         }
3243         rval = mptsas_accept_pkt(mpt, cmd);
3244 
3245         return (rval);
3246 }
3247 
3248 static int
3249 mptsas_accept_pkt(mptsas_t *mpt, mptsas_cmd_t *cmd)
3250 {
3251         int             rval = TRAN_ACCEPT;
3252         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3253 
3254         NDBG1(("mptsas_accept_pkt: cmd=0x%p", (void *)cmd));
3255 
3256         ASSERT(mutex_owned(&mpt->m_mutex));
3257 
3258         if ((cmd->cmd_flags & CFLAG_PREPARED) == 0) {
3259                 rval = mptsas_prepare_pkt(cmd);
3260                 if (rval != TRAN_ACCEPT) {
3261                         cmd->cmd_flags &= ~CFLAG_TRANFLAG;
3262                         return (rval);
3263                 }
3264         }
3265 
3266         /*
3267          * reset the throttle if we were draining
3268          */
3269         if ((ptgt->m_t_ncmds == 0) &&
3270             (ptgt->m_t_throttle == DRAIN_THROTTLE)) {
3271                 NDBG23(("reset throttle"));
3272                 ASSERT(ptgt->m_reset_delay == 0);
3273                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
3274         }
3275 
3276         /*
3277          * If HBA is being reset, the DevHandles are being re-initialized,
3278          * which means that they could be invalid even if the target is still
3279          * attached.  Check if being reset and if DevHandle is being
3280          * re-initialized.  If this is the case, return BUSY so the I/O can be
3281          * retried later.
3282          */
3283         if ((ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) && mpt->m_in_reset) {
3284                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
3285                 if (cmd->cmd_flags & CFLAG_TXQ) {
3286                         mptsas_doneq_add(mpt, cmd);
3287                         mptsas_doneq_empty(mpt);
3288                         return (rval);
3289                 } else {
3290                         return (TRAN_BUSY);
3291                 }
3292         }
3293 
3294         /*
3295          * If device handle has already been invalidated, just
3296          * fail the command. In theory, command from scsi_vhci
3297          * client is impossible send down command with invalid
3298          * devhdl since devhdl is set after path offline, target
3299          * driver is not suppose to select a offlined path.
3300          */
3301         if (ptgt->m_devhdl == MPTSAS_INVALID_DEVHDL) {
3302                 NDBG3(("rejecting command, it might because invalid devhdl "
3303                     "request."));
3304                 mptsas_set_pkt_reason(mpt, cmd, CMD_DEV_GONE, STAT_TERMINATED);
3305                 if (cmd->cmd_flags & CFLAG_TXQ) {
3306                         mptsas_doneq_add(mpt, cmd);
3307                         mptsas_doneq_empty(mpt);
3308                         return (rval);
3309                 } else {
3310                         return (TRAN_FATAL_ERROR);
3311                 }
3312         }
3313         /*
3314          * The first case is the normal case.  mpt gets a command from the
3315          * target driver and starts it.
3316          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
3317          * commands is m_max_requests - 2.
3318          */
3319         if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
3320             (ptgt->m_t_throttle > HOLD_THROTTLE) &&
3321             (ptgt->m_t_ncmds < ptgt->m_t_throttle) &&
3322             (ptgt->m_reset_delay == 0) &&
3323             (ptgt->m_t_nwait == 0) &&
3324             ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0)) {
3325                 if (mptsas_save_cmd(mpt, cmd) == TRUE) {
3326                         (void) mptsas_start_cmd(mpt, cmd);
3327                 } else {
3328                         mptsas_waitq_add(mpt, cmd);
3329                 }
3330         } else {
3331                 /*
3332                  * Add this pkt to the work queue
3333                  */
3334                 mptsas_waitq_add(mpt, cmd);
3335 
3336                 if (cmd->cmd_pkt_flags & FLAG_NOINTR) {
3337                         (void) mptsas_poll(mpt, cmd, MPTSAS_POLL_TIME);
3338 
3339                         /*
3340                          * Only flush the doneq if this is not a TM
3341                          * cmd.  For TM cmds the flushing of the
3342                          * doneq will be done in those routines.
3343                          */
3344                         if ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
3345                                 mptsas_doneq_empty(mpt);
3346                         }
3347                 }
3348         }
3349         return (rval);
3350 }
3351 
3352 int
3353 mptsas_save_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
3354 {
3355         mptsas_slots_t *slots = mpt->m_active;
3356         uint_t slot, start_rotor;
3357         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
3358 
3359         ASSERT(MUTEX_HELD(&mpt->m_mutex));
3360 
3361         /*
3362          * Account for reserved TM request slot and reserved SMID of 0.
3363          */
3364         ASSERT(slots->m_n_normal == (mpt->m_max_requests - 2));
3365 
3366         /*
3367          * Find the next available slot, beginning at m_rotor.  If no slot is
3368          * available, we'll return FALSE to indicate that.  This mechanism
3369          * considers only the normal slots, not the reserved slot 0 nor the
3370          * task management slot m_n_normal + 1.  The rotor is left to point to
3371          * the normal slot after the one we select, unless we select the last
3372          * normal slot in which case it returns to slot 1.
3373          */
3374         start_rotor = slots->m_rotor;
3375         do {
3376                 slot = slots->m_rotor++;
3377                 if (slots->m_rotor > slots->m_n_normal)
3378                         slots->m_rotor = 1;
3379 
3380                 if (slots->m_rotor == start_rotor)
3381                         break;
3382         } while (slots->m_slot[slot] != NULL);
3383 
3384         if (slots->m_slot[slot] != NULL)
3385                 return (FALSE);
3386 
3387         ASSERT(slot != 0 && slot <= slots->m_n_normal);
3388 
3389         cmd->cmd_slot = slot;
3390         slots->m_slot[slot] = cmd;
3391         mpt->m_ncmds++;
3392 
3393         /*
3394          * only increment per target ncmds if this is not a
3395          * command that has no target associated with it (i.e. a
3396          * event acknoledgment)
3397          */
3398         if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
3399                 /*
3400                  * Expiration time is set in mptsas_start_cmd
3401                  */
3402                 ptgt->m_t_ncmds++;
3403                 cmd->cmd_active_expiration = 0;
3404         } else {
3405                 /*
3406                  * Initialize expiration time for passthrough commands,
3407                  */
3408                 cmd->cmd_active_expiration = gethrtime() +
3409                     (hrtime_t)cmd->cmd_pkt->pkt_time * NANOSEC;
3410         }
3411         return (TRUE);
3412 }
3413 
3414 /*
3415  * prepare the pkt:
3416  * the pkt may have been resubmitted or just reused so
3417  * initialize some fields and do some checks.
3418  */
3419 static int
3420 mptsas_prepare_pkt(mptsas_cmd_t *cmd)
3421 {
3422         struct scsi_pkt *pkt = CMD2PKT(cmd);
3423 
3424         NDBG1(("mptsas_prepare_pkt: cmd=0x%p", (void *)cmd));
3425 
3426         /*
3427          * Reinitialize some fields that need it; the packet may
3428          * have been resubmitted
3429          */
3430         pkt->pkt_reason = CMD_CMPLT;
3431         pkt->pkt_state = 0;
3432         pkt->pkt_statistics = 0;
3433         pkt->pkt_resid = 0;
3434         cmd->cmd_age = 0;
3435         cmd->cmd_pkt_flags = pkt->pkt_flags;
3436 
3437         /*
3438          * zero status byte.
3439          */
3440         *(pkt->pkt_scbp) = 0;
3441 
3442         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3443                 pkt->pkt_resid = cmd->cmd_dmacount;
3444 
3445                 /*
3446                  * consistent packets need to be sync'ed first
3447                  * (only for data going out)
3448                  */
3449                 if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
3450                     (cmd->cmd_flags & CFLAG_DMASEND)) {
3451                         (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
3452                             DDI_DMA_SYNC_FORDEV);
3453                 }
3454         }
3455 
3456         cmd->cmd_flags =
3457             (cmd->cmd_flags & ~(CFLAG_TRANFLAG)) |
3458             CFLAG_PREPARED | CFLAG_IN_TRANSPORT;
3459 
3460         return (TRAN_ACCEPT);
3461 }
3462 
3463 /*
3464  * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command
3465  *
3466  * One of three possibilities:
3467  *      - allocate scsi_pkt
3468  *      - allocate scsi_pkt and DMA resources
3469  *      - allocate DMA resources to an already-allocated pkt
3470  */
3471 static struct scsi_pkt *
3472 mptsas_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
3473     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
3474     int (*callback)(), caddr_t arg)
3475 {
3476         mptsas_cmd_t            *cmd, *new_cmd;
3477         mptsas_t                *mpt = ADDR2MPT(ap);
3478         int                     failure = 1;
3479         uint_t                  oldcookiec;
3480         mptsas_target_t         *ptgt = NULL;
3481         int                     rval;
3482         mptsas_tgt_private_t    *tgt_private;
3483         int                     kf;
3484 
3485         kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
3486 
3487         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
3488             tran_tgt_private;
3489         ASSERT(tgt_private != NULL);
3490         if (tgt_private == NULL) {
3491                 return (NULL);
3492         }
3493         ptgt = tgt_private->t_private;
3494         ASSERT(ptgt != NULL);
3495         if (ptgt == NULL)
3496                 return (NULL);
3497         ap->a_target = ptgt->m_devhdl;
3498         ap->a_lun = tgt_private->t_lun;
3499 
3500         ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
3501 #ifdef MPTSAS_TEST_EXTRN_ALLOC
3502         statuslen *= 100; tgtlen *= 4;
3503 #endif
3504         NDBG3(("mptsas_scsi_init_pkt:\n"
3505             "\ttgt=%d in=0x%p bp=0x%p clen=%d slen=%d tlen=%d flags=%x",
3506             ap->a_target, (void *)pkt, (void *)bp,
3507             cmdlen, statuslen, tgtlen, flags));
3508 
3509         /*
3510          * Allocate the new packet.
3511          */
3512         if (pkt == NULL) {
3513                 ddi_dma_handle_t        save_dma_handle;
3514                 ddi_dma_handle_t        save_arq_dma_handle;
3515                 struct buf              *save_arq_bp;
3516                 ddi_dma_cookie_t        save_arqcookie;
3517 
3518                 cmd = kmem_cache_alloc(mpt->m_kmem_cache, kf);
3519 
3520                 if (cmd) {
3521                         save_dma_handle = cmd->cmd_dmahandle;
3522                         save_arq_dma_handle = cmd->cmd_arqhandle;
3523                         save_arq_bp = cmd->cmd_arq_buf;
3524                         save_arqcookie = cmd->cmd_arqcookie;
3525                         bzero(cmd, sizeof (*cmd) + scsi_pkt_size());
3526                         cmd->cmd_dmahandle = save_dma_handle;
3527                         cmd->cmd_arqhandle = save_arq_dma_handle;
3528                         cmd->cmd_arq_buf = save_arq_bp;
3529                         cmd->cmd_arqcookie = save_arqcookie;
3530 
3531                         pkt = (void *)((uchar_t *)cmd +
3532                             sizeof (struct mptsas_cmd));
3533                         pkt->pkt_ha_private = (opaque_t)cmd;
3534                         pkt->pkt_address = *ap;
3535                         pkt->pkt_private = (opaque_t)cmd->cmd_pkt_private;
3536                         pkt->pkt_scbp = (opaque_t)&cmd->cmd_scb;
3537                         pkt->pkt_cdbp = (opaque_t)&cmd->cmd_cdb;
3538                         cmd->cmd_pkt = (struct scsi_pkt *)pkt;
3539                         cmd->cmd_cdblen = (uchar_t)cmdlen;
3540                         cmd->cmd_scblen = statuslen;
3541                         cmd->cmd_rqslen = SENSE_LENGTH;
3542                         cmd->cmd_tgt_addr = ptgt;
3543                         failure = 0;
3544                 }
3545 
3546                 if (failure || (cmdlen > sizeof (cmd->cmd_cdb)) ||
3547                     (tgtlen > PKT_PRIV_LEN) ||
3548                     (statuslen > EXTCMDS_STATUS_SIZE)) {
3549                         if (failure == 0) {
3550                                 /*
3551                                  * if extern alloc fails, all will be
3552                                  * deallocated, including cmd
3553                                  */
3554                                 failure = mptsas_pkt_alloc_extern(mpt, cmd,
3555                                     cmdlen, tgtlen, statuslen, kf);
3556                         }
3557                         if (failure) {
3558                                 /*
3559                                  * if extern allocation fails, it will
3560                                  * deallocate the new pkt as well
3561                                  */
3562                                 return (NULL);
3563                         }
3564                 }
3565                 new_cmd = cmd;
3566 
3567         } else {
3568                 cmd = PKT2CMD(pkt);
3569                 new_cmd = NULL;
3570         }
3571 
3572 
3573         /* grab cmd->cmd_cookiec here as oldcookiec */
3574 
3575         oldcookiec = cmd->cmd_cookiec;
3576 
3577         /*
3578          * If the dma was broken up into PARTIAL transfers cmd_nwin will be
3579          * greater than 0 and we'll need to grab the next dma window
3580          */
3581         /*
3582          * SLM-not doing extra command frame right now; may add later
3583          */
3584 
3585         if (cmd->cmd_nwin > 0) {
3586 
3587                 /*
3588                  * Make sure we havn't gone past the the total number
3589                  * of windows
3590                  */
3591                 if (++cmd->cmd_winindex >= cmd->cmd_nwin) {
3592                         return (NULL);
3593                 }
3594                 if (ddi_dma_getwin(cmd->cmd_dmahandle, cmd->cmd_winindex,
3595                     &cmd->cmd_dma_offset, &cmd->cmd_dma_len,
3596                     &cmd->cmd_cookie, &cmd->cmd_cookiec) == DDI_FAILURE) {
3597                         return (NULL);
3598                 }
3599                 goto get_dma_cookies;
3600         }
3601 
3602 
3603         if (flags & PKT_XARQ) {
3604                 cmd->cmd_flags |= CFLAG_XARQ;
3605         }
3606 
3607         /*
3608          * DMA resource allocation.  This version assumes your
3609          * HBA has some sort of bus-mastering or onboard DMA capability, with a
3610          * scatter-gather list of length MPTSAS_MAX_DMA_SEGS, as given in the
3611          * ddi_dma_attr_t structure and passed to scsi_impl_dmaget.
3612          */
3613         if (bp && (bp->b_bcount != 0) &&
3614             (cmd->cmd_flags & CFLAG_DMAVALID) == 0) {
3615 
3616                 int     cnt, dma_flags;
3617                 mptti_t *dmap;          /* ptr to the S/G list */
3618 
3619                 /*
3620                  * Set up DMA memory and position to the next DMA segment.
3621                  */
3622                 ASSERT(cmd->cmd_dmahandle != NULL);
3623 
3624                 if (bp->b_flags & B_READ) {
3625                         dma_flags = DDI_DMA_READ;
3626                         cmd->cmd_flags &= ~CFLAG_DMASEND;
3627                 } else {
3628                         dma_flags = DDI_DMA_WRITE;
3629                         cmd->cmd_flags |= CFLAG_DMASEND;
3630                 }
3631                 if (flags & PKT_CONSISTENT) {
3632                         cmd->cmd_flags |= CFLAG_CMDIOPB;
3633                         dma_flags |= DDI_DMA_CONSISTENT;
3634                 }
3635 
3636                 if (flags & PKT_DMA_PARTIAL) {
3637                         dma_flags |= DDI_DMA_PARTIAL;
3638                 }
3639 
3640                 /*
3641                  * workaround for byte hole issue on psycho and
3642                  * schizo pre 2.1
3643                  */
3644                 if ((bp->b_flags & B_READ) && ((bp->b_flags &
3645                     (B_PAGEIO|B_REMAPPED)) != B_PAGEIO) &&
3646                     ((uintptr_t)bp->b_un.b_addr & 0x7)) {
3647                         dma_flags |= DDI_DMA_CONSISTENT;
3648                 }
3649 
3650                 rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
3651                     dma_flags, callback, arg,
3652                     &cmd->cmd_cookie, &cmd->cmd_cookiec);
3653                 if (rval == DDI_DMA_PARTIAL_MAP) {
3654                         (void) ddi_dma_numwin(cmd->cmd_dmahandle,
3655                             &cmd->cmd_nwin);
3656                         cmd->cmd_winindex = 0;
3657                         (void) ddi_dma_getwin(cmd->cmd_dmahandle,
3658                             cmd->cmd_winindex, &cmd->cmd_dma_offset,
3659                             &cmd->cmd_dma_len, &cmd->cmd_cookie,
3660                             &cmd->cmd_cookiec);
3661                 } else if (rval && (rval != DDI_DMA_MAPPED)) {
3662                         switch (rval) {
3663                         case DDI_DMA_NORESOURCES:
3664                                 bioerror(bp, 0);
3665                                 break;
3666                         case DDI_DMA_BADATTR:
3667                         case DDI_DMA_NOMAPPING:
3668                                 bioerror(bp, EFAULT);
3669                                 break;
3670                         case DDI_DMA_TOOBIG:
3671                         default:
3672                                 bioerror(bp, EINVAL);
3673                                 break;
3674                         }
3675                         cmd->cmd_flags &= ~CFLAG_DMAVALID;
3676                         if (new_cmd) {
3677                                 mptsas_scsi_destroy_pkt(ap, pkt);
3678                         }
3679                         return ((struct scsi_pkt *)NULL);
3680                 }
3681 
3682 get_dma_cookies:
3683                 cmd->cmd_flags |= CFLAG_DMAVALID;
3684                 ASSERT(cmd->cmd_cookiec > 0);
3685 
3686                 if (cmd->cmd_cookiec > MPTSAS_MAX_CMD_SEGS) {
3687                         mptsas_log(mpt, CE_NOTE, "large cookiec received %d\n",
3688                             cmd->cmd_cookiec);
3689                         bioerror(bp, EINVAL);
3690                         if (new_cmd) {
3691                                 mptsas_scsi_destroy_pkt(ap, pkt);
3692                         }
3693                         return ((struct scsi_pkt *)NULL);
3694                 }
3695 
3696                 /*
3697                  * Allocate extra SGL buffer if needed.
3698                  */
3699                 if ((cmd->cmd_cookiec > MPTSAS_MAX_FRAME_SGES64(mpt)) &&
3700                     (cmd->cmd_extra_frames == NULL)) {
3701                         if (mptsas_alloc_extra_sgl_frame(mpt, cmd) ==
3702                             DDI_FAILURE) {
3703                                 mptsas_log(mpt, CE_WARN, "MPT SGL mem alloc "
3704                                     "failed");
3705                                 bioerror(bp, ENOMEM);
3706                                 if (new_cmd) {
3707                                         mptsas_scsi_destroy_pkt(ap, pkt);
3708                                 }
3709                                 return ((struct scsi_pkt *)NULL);
3710                         }
3711                 }
3712 
3713                 /*
3714                  * Always use scatter-gather transfer
3715                  * Use the loop below to store physical addresses of
3716                  * DMA segments, from the DMA cookies, into your HBA's
3717                  * scatter-gather list.
3718                  * We need to ensure we have enough kmem alloc'd
3719                  * for the sg entries since we are no longer using an
3720                  * array inside mptsas_cmd_t.
3721                  *
3722                  * We check cmd->cmd_cookiec against oldcookiec so
3723                  * the scatter-gather list is correctly allocated
3724                  */
3725 
3726                 if (oldcookiec != cmd->cmd_cookiec) {
3727                         if (cmd->cmd_sg != (mptti_t *)NULL) {
3728                                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) *
3729                                     oldcookiec);
3730                                 cmd->cmd_sg = NULL;
3731                         }
3732                 }
3733 
3734                 if (cmd->cmd_sg == (mptti_t *)NULL) {
3735                         cmd->cmd_sg = kmem_alloc((size_t)(sizeof (mptti_t)*
3736                             cmd->cmd_cookiec), kf);
3737 
3738                         if (cmd->cmd_sg == (mptti_t *)NULL) {
3739                                 mptsas_log(mpt, CE_WARN,
3740                                     "unable to kmem_alloc enough memory "
3741                                     "for scatter/gather list");
3742                 /*
3743                  * if we have an ENOMEM condition we need to behave
3744                  * the same way as the rest of this routine
3745                  */
3746 
3747                                 bioerror(bp, ENOMEM);
3748                                 if (new_cmd) {
3749                                         mptsas_scsi_destroy_pkt(ap, pkt);
3750                                 }
3751                                 return ((struct scsi_pkt *)NULL);
3752                         }
3753                 }
3754 
3755                 dmap = cmd->cmd_sg;
3756 
3757                 ASSERT(cmd->cmd_cookie.dmac_size != 0);
3758 
3759                 /*
3760                  * store the first segment into the S/G list
3761                  */
3762                 dmap->count = cmd->cmd_cookie.dmac_size;
3763                 dmap->addr.address64.Low = (uint32_t)
3764                     (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3765                 dmap->addr.address64.High = (uint32_t)
3766                     (cmd->cmd_cookie.dmac_laddress >> 32);
3767 
3768                 /*
3769                  * dmacount counts the size of the dma for this window
3770                  * (if partial dma is being used).  totaldmacount
3771                  * keeps track of the total amount of dma we have
3772                  * transferred for all the windows (needed to calculate
3773                  * the resid value below).
3774                  */
3775                 cmd->cmd_dmacount = cmd->cmd_cookie.dmac_size;
3776                 cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3777 
3778                 /*
3779                  * We already stored the first DMA scatter gather segment,
3780                  * start at 1 if we need to store more.
3781                  */
3782                 for (cnt = 1; cnt < cmd->cmd_cookiec; cnt++) {
3783                         /*
3784                          * Get next DMA cookie
3785                          */
3786                         ddi_dma_nextcookie(cmd->cmd_dmahandle,
3787                             &cmd->cmd_cookie);
3788                         dmap++;
3789 
3790                         cmd->cmd_dmacount += cmd->cmd_cookie.dmac_size;
3791                         cmd->cmd_totaldmacount += cmd->cmd_cookie.dmac_size;
3792 
3793                         /*
3794                          * store the segment parms into the S/G list
3795                          */
3796                         dmap->count = cmd->cmd_cookie.dmac_size;
3797                         dmap->addr.address64.Low = (uint32_t)
3798                             (cmd->cmd_cookie.dmac_laddress & 0xffffffffull);
3799                         dmap->addr.address64.High = (uint32_t)
3800                             (cmd->cmd_cookie.dmac_laddress >> 32);
3801                 }
3802 
3803                 /*
3804                  * If this was partially allocated we set the resid
3805                  * the amount of data NOT transferred in this window
3806                  * If there is only one window, the resid will be 0
3807                  */
3808                 pkt->pkt_resid = (bp->b_bcount - cmd->cmd_totaldmacount);
3809                 NDBG3(("mptsas_scsi_init_pkt: cmd_dmacount=%d.",
3810                     cmd->cmd_dmacount));
3811         }
3812         return (pkt);
3813 }
3814 
3815 /*
3816  * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation
3817  *
3818  * Notes:
3819  *      - also frees DMA resources if allocated
3820  *      - implicit DMA synchonization
3821  */
3822 static void
3823 mptsas_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
3824 {
3825         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
3826         mptsas_t        *mpt = ADDR2MPT(ap);
3827 
3828         NDBG3(("mptsas_scsi_destroy_pkt: target=%d pkt=0x%p",
3829             ap->a_target, (void *)pkt));
3830 
3831         if (cmd->cmd_flags & CFLAG_DMAVALID) {
3832                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
3833                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
3834         }
3835 
3836         if (cmd->cmd_sg) {
3837                 kmem_free(cmd->cmd_sg, sizeof (mptti_t) * cmd->cmd_cookiec);
3838                 cmd->cmd_sg = NULL;
3839         }
3840 
3841         mptsas_free_extra_sgl_frame(mpt, cmd);
3842 
3843         if ((cmd->cmd_flags &
3844             (CFLAG_FREE | CFLAG_CDBEXTERN | CFLAG_PRIVEXTERN |
3845             CFLAG_SCBEXTERN)) == 0) {
3846                 cmd->cmd_flags = CFLAG_FREE;
3847                 kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
3848         } else {
3849                 mptsas_pkt_destroy_extern(mpt, cmd);
3850         }
3851 }
3852 
3853 /*
3854  * kmem cache constructor and destructor:
3855  * When constructing, we bzero the cmd and allocate the dma handle
3856  * When destructing, just free the dma handle
3857  */
3858 static int
3859 mptsas_kmem_cache_constructor(void *buf, void *cdrarg, int kmflags)
3860 {
3861         mptsas_cmd_t            *cmd = buf;
3862         mptsas_t                *mpt  = cdrarg;
3863         struct scsi_address     ap;
3864         uint_t                  cookiec;
3865         ddi_dma_attr_t          arq_dma_attr;
3866         int                     (*callback)(caddr_t);
3867 
3868         callback = (kmflags == KM_SLEEP)? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3869 
3870         NDBG4(("mptsas_kmem_cache_constructor"));
3871 
3872         ap.a_hba_tran = mpt->m_tran;
3873         ap.a_target = 0;
3874         ap.a_lun = 0;
3875 
3876         /*
3877          * allocate a dma handle
3878          */
3879         if ((ddi_dma_alloc_handle(mpt->m_dip, &mpt->m_io_dma_attr, callback,
3880             NULL, &cmd->cmd_dmahandle)) != DDI_SUCCESS) {
3881                 cmd->cmd_dmahandle = NULL;
3882                 return (-1);
3883         }
3884 
3885         cmd->cmd_arq_buf = scsi_alloc_consistent_buf(&ap, (struct buf *)NULL,
3886             SENSE_LENGTH, B_READ, callback, NULL);
3887         if (cmd->cmd_arq_buf == NULL) {
3888                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3889                 cmd->cmd_dmahandle = NULL;
3890                 return (-1);
3891         }
3892 
3893         /*
3894          * allocate a arq handle
3895          */
3896         arq_dma_attr = mpt->m_msg_dma_attr;
3897         arq_dma_attr.dma_attr_sgllen = 1;
3898         if ((ddi_dma_alloc_handle(mpt->m_dip, &arq_dma_attr, callback,
3899             NULL, &cmd->cmd_arqhandle)) != DDI_SUCCESS) {
3900                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3901                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3902                 cmd->cmd_dmahandle = NULL;
3903                 cmd->cmd_arqhandle = NULL;
3904                 return (-1);
3905         }
3906 
3907         if (ddi_dma_buf_bind_handle(cmd->cmd_arqhandle,
3908             cmd->cmd_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
3909             callback, NULL, &cmd->cmd_arqcookie, &cookiec) != DDI_SUCCESS) {
3910                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3911                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3912                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3913                 cmd->cmd_dmahandle = NULL;
3914                 cmd->cmd_arqhandle = NULL;
3915                 cmd->cmd_arq_buf = NULL;
3916                 return (-1);
3917         }
3918 
3919         return (0);
3920 }
3921 
3922 static void
3923 mptsas_kmem_cache_destructor(void *buf, void *cdrarg)
3924 {
3925 #ifndef __lock_lint
3926         _NOTE(ARGUNUSED(cdrarg))
3927 #endif
3928         mptsas_cmd_t    *cmd = buf;
3929 
3930         NDBG4(("mptsas_kmem_cache_destructor"));
3931 
3932         if (cmd->cmd_arqhandle) {
3933                 (void) ddi_dma_unbind_handle(cmd->cmd_arqhandle);
3934                 ddi_dma_free_handle(&cmd->cmd_arqhandle);
3935                 cmd->cmd_arqhandle = NULL;
3936         }
3937         if (cmd->cmd_arq_buf) {
3938                 scsi_free_consistent_buf(cmd->cmd_arq_buf);
3939                 cmd->cmd_arq_buf = NULL;
3940         }
3941         if (cmd->cmd_dmahandle) {
3942                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
3943                 cmd->cmd_dmahandle = NULL;
3944         }
3945 }
3946 
3947 static int
3948 mptsas_cache_frames_constructor(void *buf, void *cdrarg, int kmflags)
3949 {
3950         mptsas_cache_frames_t   *p = buf;
3951         mptsas_t                *mpt = cdrarg;
3952         ddi_dma_attr_t          frame_dma_attr;
3953         size_t                  mem_size, alloc_len;
3954         ddi_dma_cookie_t        cookie;
3955         uint_t                  ncookie;
3956         int (*callback)(caddr_t) = (kmflags == KM_SLEEP)
3957             ? DDI_DMA_SLEEP: DDI_DMA_DONTWAIT;
3958 
3959         frame_dma_attr = mpt->m_msg_dma_attr;
3960         frame_dma_attr.dma_attr_align = 0x10;
3961         frame_dma_attr.dma_attr_sgllen = 1;
3962 
3963         if (ddi_dma_alloc_handle(mpt->m_dip, &frame_dma_attr, callback, NULL,
3964             &p->m_dma_hdl) != DDI_SUCCESS) {
3965                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma handle for"
3966                     " extra SGL.");
3967                 return (DDI_FAILURE);
3968         }
3969 
3970         mem_size = (mpt->m_max_request_frames - 1) * mpt->m_req_frame_size;
3971 
3972         if (ddi_dma_mem_alloc(p->m_dma_hdl, mem_size, &mpt->m_dev_acc_attr,
3973             DDI_DMA_CONSISTENT, callback, NULL, (caddr_t *)&p->m_frames_addr,
3974             &alloc_len, &p->m_acc_hdl) != DDI_SUCCESS) {
3975                 ddi_dma_free_handle(&p->m_dma_hdl);
3976                 p->m_dma_hdl = NULL;
3977                 mptsas_log(mpt, CE_WARN, "Unable to allocate dma memory for"
3978                     " extra SGL.");
3979                 return (DDI_FAILURE);
3980         }
3981 
3982         if (ddi_dma_addr_bind_handle(p->m_dma_hdl, NULL, p->m_frames_addr,
3983             alloc_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, callback, NULL,
3984             &cookie, &ncookie) != DDI_DMA_MAPPED) {
3985                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
3986                 ddi_dma_free_handle(&p->m_dma_hdl);
3987                 p->m_dma_hdl = NULL;
3988                 mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
3989                     " extra SGL");
3990                 return (DDI_FAILURE);
3991         }
3992 
3993         /*
3994          * Store the SGL memory address.  This chip uses this
3995          * address to dma to and from the driver.  The second
3996          * address is the address mpt uses to fill in the SGL.
3997          */
3998         p->m_phys_addr = cookie.dmac_address;
3999 
4000         return (DDI_SUCCESS);
4001 }
4002 
4003 static void
4004 mptsas_cache_frames_destructor(void *buf, void *cdrarg)
4005 {
4006 #ifndef __lock_lint
4007         _NOTE(ARGUNUSED(cdrarg))
4008 #endif
4009         mptsas_cache_frames_t   *p = buf;
4010         if (p->m_dma_hdl != NULL) {
4011                 (void) ddi_dma_unbind_handle(p->m_dma_hdl);
4012                 (void) ddi_dma_mem_free(&p->m_acc_hdl);
4013                 ddi_dma_free_handle(&p->m_dma_hdl);
4014                 p->m_phys_addr = NULL;
4015                 p->m_frames_addr = NULL;
4016                 p->m_dma_hdl = NULL;
4017                 p->m_acc_hdl = NULL;
4018         }
4019 
4020 }
4021 
4022 /*
4023  * allocate and deallocate external pkt space (ie. not part of mptsas_cmd)
4024  * for non-standard length cdb, pkt_private, status areas
4025  * if allocation fails, then deallocate all external space and the pkt
4026  */
4027 /* ARGSUSED */
4028 static int
4029 mptsas_pkt_alloc_extern(mptsas_t *mpt, mptsas_cmd_t *cmd,
4030     int cmdlen, int tgtlen, int statuslen, int kf)
4031 {
4032         caddr_t                 cdbp, scbp, tgt;
4033         int                     (*callback)(caddr_t) = (kf == KM_SLEEP) ?
4034             DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
4035         struct scsi_address     ap;
4036         size_t                  senselength;
4037         ddi_dma_attr_t          ext_arq_dma_attr;
4038         uint_t                  cookiec;
4039 
4040         NDBG3(("mptsas_pkt_alloc_extern: "
4041             "cmd=0x%p cmdlen=%d tgtlen=%d statuslen=%d kf=%x",
4042             (void *)cmd, cmdlen, tgtlen, statuslen, kf));
4043 
4044         tgt = cdbp = scbp = NULL;
4045         cmd->cmd_scblen              = statuslen;
4046         cmd->cmd_privlen     = (uchar_t)tgtlen;
4047 
4048         if (cmdlen > sizeof (cmd->cmd_cdb)) {
4049                 if ((cdbp = kmem_zalloc((size_t)cmdlen, kf)) == NULL) {
4050                         goto fail;
4051                 }
4052                 cmd->cmd_pkt->pkt_cdbp = (opaque_t)cdbp;
4053                 cmd->cmd_flags |= CFLAG_CDBEXTERN;
4054         }
4055         if (tgtlen > PKT_PRIV_LEN) {
4056                 if ((tgt = kmem_zalloc((size_t)tgtlen, kf)) == NULL) {
4057                         goto fail;
4058                 }
4059                 cmd->cmd_flags |= CFLAG_PRIVEXTERN;
4060                 cmd->cmd_pkt->pkt_private = tgt;
4061         }
4062         if (statuslen > EXTCMDS_STATUS_SIZE) {
4063                 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
4064                         goto fail;
4065                 }
4066                 cmd->cmd_flags |= CFLAG_SCBEXTERN;
4067                 cmd->cmd_pkt->pkt_scbp = (opaque_t)scbp;
4068 
4069                 /* allocate sense data buf for DMA */
4070 
4071                 senselength = statuslen - MPTSAS_GET_ITEM_OFF(
4072                     struct scsi_arq_status, sts_sensedata);
4073                 cmd->cmd_rqslen = (uchar_t)senselength;
4074 
4075                 ap.a_hba_tran = mpt->m_tran;
4076                 ap.a_target = 0;
4077                 ap.a_lun = 0;
4078 
4079                 cmd->cmd_ext_arq_buf = scsi_alloc_consistent_buf(&ap,
4080                     (struct buf *)NULL, senselength, B_READ,
4081                     callback, NULL);
4082 
4083                 if (cmd->cmd_ext_arq_buf == NULL) {
4084                         goto fail;
4085                 }
4086                 /*
4087                  * allocate a extern arq handle and bind the buf
4088                  */
4089                 ext_arq_dma_attr = mpt->m_msg_dma_attr;
4090                 ext_arq_dma_attr.dma_attr_sgllen = 1;
4091                 if ((ddi_dma_alloc_handle(mpt->m_dip,
4092                     &ext_arq_dma_attr, callback,
4093                     NULL, &cmd->cmd_ext_arqhandle)) != DDI_SUCCESS) {
4094                         goto fail;
4095                 }
4096 
4097                 if (ddi_dma_buf_bind_handle(cmd->cmd_ext_arqhandle,
4098                     cmd->cmd_ext_arq_buf, (DDI_DMA_READ | DDI_DMA_CONSISTENT),
4099                     callback, NULL, &cmd->cmd_ext_arqcookie,
4100                     &cookiec)
4101                     != DDI_SUCCESS) {
4102                         goto fail;
4103                 }
4104                 cmd->cmd_flags |= CFLAG_EXTARQBUFVALID;
4105         }
4106         return (0);
4107 fail:
4108         mptsas_pkt_destroy_extern(mpt, cmd);
4109         return (1);
4110 }
4111 
4112 /*
4113  * deallocate external pkt space and deallocate the pkt
4114  */
4115 static void
4116 mptsas_pkt_destroy_extern(mptsas_t *mpt, mptsas_cmd_t *cmd)
4117 {
4118         NDBG3(("mptsas_pkt_destroy_extern: cmd=0x%p", (void *)cmd));
4119 
4120         if (cmd->cmd_flags & CFLAG_FREE) {
4121                 mptsas_log(mpt, CE_PANIC,
4122                     "mptsas_pkt_destroy_extern: freeing free packet");
4123                 _NOTE(NOT_REACHED)
4124                 /* NOTREACHED */
4125         }
4126         if (cmd->cmd_flags & CFLAG_CDBEXTERN) {
4127                 kmem_free(cmd->cmd_pkt->pkt_cdbp, (size_t)cmd->cmd_cdblen);
4128         }
4129         if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
4130                 kmem_free(cmd->cmd_pkt->pkt_scbp, (size_t)cmd->cmd_scblen);
4131                 if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4132                         (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4133                 }
4134                 if (cmd->cmd_ext_arqhandle) {
4135                         ddi_dma_free_handle(&cmd->cmd_ext_arqhandle);
4136                         cmd->cmd_ext_arqhandle = NULL;
4137                 }
4138                 if (cmd->cmd_ext_arq_buf)
4139                         scsi_free_consistent_buf(cmd->cmd_ext_arq_buf);
4140         }
4141         if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
4142                 kmem_free(cmd->cmd_pkt->pkt_private, (size_t)cmd->cmd_privlen);
4143         }
4144         cmd->cmd_flags = CFLAG_FREE;
4145         kmem_cache_free(mpt->m_kmem_cache, (void *)cmd);
4146 }
4147 
4148 /*
4149  * tran_sync_pkt(9E) - explicit DMA synchronization
4150  */
4151 /*ARGSUSED*/
4152 static void
4153 mptsas_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
4154 {
4155         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4156 
4157         NDBG3(("mptsas_scsi_sync_pkt: target=%d, pkt=0x%p",
4158             ap->a_target, (void *)pkt));
4159 
4160         if (cmd->cmd_dmahandle) {
4161                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4162                     (cmd->cmd_flags & CFLAG_DMASEND) ?
4163                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU);
4164         }
4165 }
4166 
4167 /*
4168  * tran_dmafree(9E) - deallocate DMA resources allocated for command
4169  */
4170 /*ARGSUSED*/
4171 static void
4172 mptsas_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
4173 {
4174         mptsas_cmd_t    *cmd = PKT2CMD(pkt);
4175         mptsas_t        *mpt = ADDR2MPT(ap);
4176 
4177         NDBG3(("mptsas_scsi_dmafree: target=%d pkt=0x%p",
4178             ap->a_target, (void *)pkt));
4179 
4180         if (cmd->cmd_flags & CFLAG_DMAVALID) {
4181                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
4182                 cmd->cmd_flags &= ~CFLAG_DMAVALID;
4183         }
4184 
4185         if (cmd->cmd_flags & CFLAG_EXTARQBUFVALID) {
4186                 (void) ddi_dma_unbind_handle(cmd->cmd_ext_arqhandle);
4187                 cmd->cmd_flags &= ~CFLAG_EXTARQBUFVALID;
4188         }
4189 
4190         mptsas_free_extra_sgl_frame(mpt, cmd);
4191 }
4192 
4193 static void
4194 mptsas_pkt_comp(struct scsi_pkt *pkt, mptsas_cmd_t *cmd)
4195 {
4196         if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4197             (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4198                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4199                     DDI_DMA_SYNC_FORCPU);
4200         }
4201         (*pkt->pkt_comp)(pkt);
4202 }
4203 
4204 static void
4205 mptsas_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
4206     ddi_acc_handle_t acc_hdl, uint_t cookiec, uint32_t end_flags)
4207 {
4208         pMpi2SGESimple64_t      sge;
4209         mptti_t                 *dmap;
4210         uint32_t                flags;
4211 
4212         dmap = cmd->cmd_sg;
4213 
4214         sge = (pMpi2SGESimple64_t)(&frame->SGL);
4215         while (cookiec--) {
4216                 ddi_put32(acc_hdl,
4217                     &sge->Address.Low, dmap->addr.address64.Low);
4218                 ddi_put32(acc_hdl,
4219                     &sge->Address.High, dmap->addr.address64.High);
4220                 ddi_put32(acc_hdl, &sge->FlagsLength,
4221                     dmap->count);
4222                 flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4223                 flags |= ((uint32_t)
4224                     (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4225                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4226                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4227                     MPI2_SGE_FLAGS_SHIFT);
4228 
4229                 /*
4230                  * If this is the last cookie, we set the flags
4231                  * to indicate so
4232                  */
4233                 if (cookiec == 0) {
4234                         flags |= end_flags;
4235                 }
4236                 if (cmd->cmd_flags & CFLAG_DMASEND) {
4237                         flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4238                             MPI2_SGE_FLAGS_SHIFT);
4239                 } else {
4240                         flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4241                             MPI2_SGE_FLAGS_SHIFT);
4242                 }
4243                 ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4244                 dmap++;
4245                 sge++;
4246         }
4247 }
4248 
4249 static void
4250 mptsas_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
4251     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4252 {
4253         pMpi2SGESimple64_t      sge;
4254         pMpi2SGEChain64_t       sgechain;
4255         uint_t                  cookiec;
4256         mptti_t                 *dmap;
4257         uint32_t                flags;
4258 
4259         /*
4260          * Save the number of entries in the DMA
4261          * Scatter/Gather list
4262          */
4263         cookiec = cmd->cmd_cookiec;
4264 
4265         /*
4266          * Hereby we start to deal with multiple frames.
4267          * The process is as follows:
4268          * 1. Determine how many frames are needed for SGL element
4269          *    storage; Note that all frames are stored in contiguous
4270          *    memory space and in 64-bit DMA mode each element is
4271          *    3 double-words (12 bytes) long.
4272          * 2. Fill up the main frame. We need to do this separately
4273          *    since it contains the SCSI IO request header and needs
4274          *    dedicated processing. Note that the last 4 double-words
4275          *    of the SCSI IO header is for SGL element storage
4276          *    (MPI2_SGE_IO_UNION).
4277          * 3. Fill the chain element in the main frame, so the DMA
4278          *    engine can use the following frames.
4279          * 4. Enter a loop to fill the remaining frames. Note that the
4280          *    last frame contains no chain element.  The remaining
4281          *    frames go into the mpt SGL buffer allocated on the fly,
4282          *    not immediately following the main message frame, as in
4283          *    Gen1.
4284          * Some restrictions:
4285          * 1. For 64-bit DMA, the simple element and chain element
4286          *    are both of 3 double-words (12 bytes) in size, even
4287          *    though all frames are stored in the first 4G of mem
4288          *    range and the higher 32-bits of the address are always 0.
4289          * 2. On some controllers (like the 1064/1068), a frame can
4290          *    hold SGL elements with the last 1 or 2 double-words
4291          *    (4 or 8 bytes) un-used. On these controllers, we should
4292          *    recognize that there's not enough room for another SGL
4293          *    element and move the sge pointer to the next frame.
4294          */
4295         int                     i, j, k, l, frames, sgemax;
4296         int                     temp;
4297         uint8_t                 chainflags;
4298         uint16_t                chainlength;
4299         mptsas_cache_frames_t   *p;
4300 
4301         /*
4302          * Sgemax is the number of SGE's that will fit
4303          * each extra frame and frames is total
4304          * number of frames we'll need.  1 sge entry per
4305          * frame is reseverd for the chain element thus the -1 below.
4306          */
4307         sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4308             - 1);
4309         temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4310 
4311         /*
4312          * A little check to see if we need to round up the number
4313          * of frames we need
4314          */
4315         if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4316             sgemax) > 1) {
4317                 frames = (temp + 1);
4318         } else {
4319                 frames = temp;
4320         }
4321         dmap = cmd->cmd_sg;
4322         sge = (pMpi2SGESimple64_t)(&frame->SGL);
4323 
4324         /*
4325          * First fill in the main frame
4326          */
4327         j = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
4328         mptsas_sge_mainframe(cmd, frame, acc_hdl, j,
4329             ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4330             MPI2_SGE_FLAGS_SHIFT));
4331         dmap += j;
4332         sge += j;
4333         j++;
4334 
4335         /*
4336          * Fill in the chain element in the main frame.
4337          * About calculation on ChainOffset:
4338          * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4339          *    in the end reserved for SGL element storage
4340          *    (MPI2_SGE_IO_UNION); we should count it in our
4341          *    calculation.  See its definition in the header file.
4342          * 2. Constant j is the counter of the current SGL element
4343          *    that will be processed, and (j - 1) is the number of
4344          *    SGL elements that have been processed (stored in the
4345          *    main frame).
4346          * 3. ChainOffset value should be in units of double-words (4
4347          *    bytes) so the last value should be divided by 4.
4348          */
4349         ddi_put8(acc_hdl, &frame->ChainOffset,
4350             (sizeof (MPI2_SCSI_IO_REQUEST) -
4351             sizeof (MPI2_SGE_IO_UNION) +
4352             (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4353         sgechain = (pMpi2SGEChain64_t)sge;
4354         chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4355             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4356             MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4357         ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4358 
4359         /*
4360          * The size of the next frame is the accurate size of space
4361          * (in bytes) used to store the SGL elements. j is the counter
4362          * of SGL elements. (j - 1) is the number of SGL elements that
4363          * have been processed (stored in frames).
4364          */
4365         if (frames >= 2) {
4366                 ASSERT(mpt->m_req_frame_size >= sizeof (MPI2_SGE_SIMPLE64));
4367                 chainlength = mpt->m_req_frame_size /
4368                     sizeof (MPI2_SGE_SIMPLE64) *
4369                     sizeof (MPI2_SGE_SIMPLE64);
4370         } else {
4371                 chainlength = ((cookiec - (j - 1)) *
4372                     sizeof (MPI2_SGE_SIMPLE64));
4373         }
4374 
4375         p = cmd->cmd_extra_frames;
4376 
4377         ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4378         ddi_put32(acc_hdl, &sgechain->Address.Low,
4379             p->m_phys_addr);
4380         /* SGL is allocated in the first 4G mem range */
4381         ddi_put32(acc_hdl, &sgechain->Address.High, 0);
4382 
4383         /*
4384          * If there are more than 2 frames left we have to
4385          * fill in the next chain offset to the location of
4386          * the chain element in the next frame.
4387          * sgemax is the number of simple elements in an extra
4388          * frame. Note that the value NextChainOffset should be
4389          * in double-words (4 bytes).
4390          */
4391         if (frames >= 2) {
4392                 ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4393                     (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4394         } else {
4395                 ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
4396         }
4397 
4398         /*
4399          * Jump to next frame;
4400          * Starting here, chain buffers go into the per command SGL.
4401          * This buffer is allocated when chain buffers are needed.
4402          */
4403         sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4404         i = cookiec;
4405 
4406         /*
4407          * Start filling in frames with SGE's.  If we
4408          * reach the end of frame and still have SGE's
4409          * to fill we need to add a chain element and
4410          * use another frame.  j will be our counter
4411          * for what cookie we are at and i will be
4412          * the total cookiec. k is the current frame
4413          */
4414         for (k = 1; k <= frames; k++) {
4415                 for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4416 
4417                         /*
4418                          * If we have reached the end of frame
4419                          * and we have more SGE's to fill in
4420                          * we have to fill the final entry
4421                          * with a chain element and then
4422                          * continue to the next frame
4423                          */
4424                         if ((l == (sgemax + 1)) && (k != frames)) {
4425                                 sgechain = (pMpi2SGEChain64_t)sge;
4426                                 j--;
4427                                 chainflags = (
4428                                     MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4429                                     MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4430                                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4431                                 ddi_put8(p->m_acc_hdl,
4432                                     &sgechain->Flags, chainflags);
4433                                 /*
4434                                  * k is the frame counter and (k + 1)
4435                                  * is the number of the next frame.
4436                                  * Note that frames are in contiguous
4437                                  * memory space.
4438                                  */
4439                                 ddi_put32(p->m_acc_hdl,
4440                                     &sgechain->Address.Low,
4441                                     (p->m_phys_addr +
4442                                     (mpt->m_req_frame_size * k)));
4443                                 ddi_put32(p->m_acc_hdl,
4444                                     &sgechain->Address.High, 0);
4445 
4446                                 /*
4447                                  * If there are more than 2 frames left
4448                                  * we have to next chain offset to
4449                                  * the location of the chain element
4450                                  * in the next frame and fill in the
4451                                  * length of the next chain
4452                                  */
4453                                 if ((frames - k) >= 2) {
4454                                         ddi_put8(p->m_acc_hdl,
4455                                             &sgechain->NextChainOffset,
4456                                             (sgemax *
4457                                             sizeof (MPI2_SGE_SIMPLE64))
4458                                             >> 2);
4459                                         ddi_put16(p->m_acc_hdl,
4460                                             &sgechain->Length,
4461                                             mpt->m_req_frame_size /
4462                                             sizeof (MPI2_SGE_SIMPLE64) *
4463                                             sizeof (MPI2_SGE_SIMPLE64));
4464                                 } else {
4465                                         /*
4466                                          * This is the last frame. Set
4467                                          * the NextChainOffset to 0 and
4468                                          * Length is the total size of
4469                                          * all remaining simple elements
4470                                          */
4471                                         ddi_put8(p->m_acc_hdl,
4472                                             &sgechain->NextChainOffset,
4473                                             0);
4474                                         ddi_put16(p->m_acc_hdl,
4475                                             &sgechain->Length,
4476                                             (cookiec - j) *
4477                                             sizeof (MPI2_SGE_SIMPLE64));
4478                                 }
4479 
4480                                 /* Jump to the next frame */
4481                                 sge = (pMpi2SGESimple64_t)
4482                                     ((char *)p->m_frames_addr +
4483                                     (int)mpt->m_req_frame_size * k);
4484 
4485                                 continue;
4486                         }
4487 
4488                         ddi_put32(p->m_acc_hdl,
4489                             &sge->Address.Low,
4490                             dmap->addr.address64.Low);
4491                         ddi_put32(p->m_acc_hdl,
4492                             &sge->Address.High,
4493                             dmap->addr.address64.High);
4494                         ddi_put32(p->m_acc_hdl,
4495                             &sge->FlagsLength, dmap->count);
4496                         flags = ddi_get32(p->m_acc_hdl,
4497                             &sge->FlagsLength);
4498                         flags |= ((uint32_t)(
4499                             MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4500                             MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4501                             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4502                             MPI2_SGE_FLAGS_SHIFT);
4503 
4504                         /*
4505                          * If we are at the end of the frame and
4506                          * there is another frame to fill in
4507                          * we set the last simple element as last
4508                          * element
4509                          */
4510                         if ((l == sgemax) && (k != frames)) {
4511                                 flags |= ((uint32_t)
4512                                     (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4513                                     MPI2_SGE_FLAGS_SHIFT);
4514                         }
4515 
4516                         /*
4517                          * If this is the final cookie we
4518                          * indicate it by setting the flags
4519                          */
4520                         if (j == i) {
4521                                 flags |= ((uint32_t)
4522                                     (MPI2_SGE_FLAGS_LAST_ELEMENT |
4523                                     MPI2_SGE_FLAGS_END_OF_BUFFER |
4524                                     MPI2_SGE_FLAGS_END_OF_LIST) <<
4525                                     MPI2_SGE_FLAGS_SHIFT);
4526                         }
4527                         if (cmd->cmd_flags & CFLAG_DMASEND) {
4528                                 flags |=
4529                                     (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4530                                     MPI2_SGE_FLAGS_SHIFT);
4531                         } else {
4532                                 flags |=
4533                                     (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4534                                     MPI2_SGE_FLAGS_SHIFT);
4535                         }
4536                         ddi_put32(p->m_acc_hdl,
4537                             &sge->FlagsLength, flags);
4538                         dmap++;
4539                         sge++;
4540                 }
4541         }
4542 
4543         /*
4544          * Sync DMA with the chain buffers that were just created
4545          */
4546         (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4547 }
4548 
4549 static void
4550 mptsas_ieee_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
4551     ddi_acc_handle_t acc_hdl, uint_t cookiec, uint8_t end_flag)
4552 {
4553         pMpi2IeeeSgeSimple64_t  ieeesge;
4554         mptti_t                 *dmap;
4555         uint8_t                 flags;
4556 
4557         dmap = cmd->cmd_sg;
4558 
4559         NDBG1(("mptsas_ieee_sge_mainframe: cookiec=%d, %s", cookiec,
4560             cmd->cmd_flags & CFLAG_DMASEND?"Out":"In"));
4561 
4562         ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
4563         while (cookiec--) {
4564                 ddi_put32(acc_hdl,
4565                     &ieeesge->Address.Low, dmap->addr.address64.Low);
4566                 ddi_put32(acc_hdl,
4567                     &ieeesge->Address.High, dmap->addr.address64.High);
4568                 ddi_put32(acc_hdl, &ieeesge->Length,
4569                     dmap->count);
4570                 NDBG1(("mptsas_ieee_sge_mainframe: len=%d", dmap->count));
4571                 flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
4572                     MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4573 
4574                 /*
4575                  * If this is the last cookie, we set the flags
4576                  * to indicate so
4577                  */
4578                 if (cookiec == 0) {
4579                         flags |= end_flag;
4580                 }
4581 
4582                 ddi_put8(acc_hdl, &ieeesge->Flags, flags);
4583                 dmap++;
4584                 ieeesge++;
4585         }
4586 }
4587 
4588 static void
4589 mptsas_ieee_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
4590     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4591 {
4592         pMpi2IeeeSgeSimple64_t  ieeesge;
4593         pMpi25IeeeSgeChain64_t  ieeesgechain;
4594         uint_t                  cookiec;
4595         mptti_t                 *dmap;
4596         uint8_t                 flags;
4597 
4598         /*
4599          * Save the number of entries in the DMA
4600          * Scatter/Gather list
4601          */
4602         cookiec = cmd->cmd_cookiec;
4603 
4604         NDBG1(("mptsas_ieee_sge_chain: cookiec=%d", cookiec));
4605 
4606         /*
4607          * Hereby we start to deal with multiple frames.
4608          * The process is as follows:
4609          * 1. Determine how many frames are needed for SGL element
4610          *    storage; Note that all frames are stored in contiguous
4611          *    memory space and in 64-bit DMA mode each element is
4612          *    4 double-words (16 bytes) long.
4613          * 2. Fill up the main frame. We need to do this separately
4614          *    since it contains the SCSI IO request header and needs
4615          *    dedicated processing. Note that the last 4 double-words
4616          *    of the SCSI IO header is for SGL element storage
4617          *    (MPI2_SGE_IO_UNION).
4618          * 3. Fill the chain element in the main frame, so the DMA
4619          *    engine can use the following frames.
4620          * 4. Enter a loop to fill the remaining frames. Note that the
4621          *    last frame contains no chain element.  The remaining
4622          *    frames go into the mpt SGL buffer allocated on the fly,
4623          *    not immediately following the main message frame, as in
4624          *    Gen1.
4625          * Restrictions:
4626          *    For 64-bit DMA, the simple element and chain element
4627          *    are both of 4 double-words (16 bytes) in size, even
4628          *    though all frames are stored in the first 4G of mem
4629          *    range and the higher 32-bits of the address are always 0.
4630          */
4631         int                     i, j, k, l, frames, sgemax;
4632         int                     temp;
4633         uint8_t                 chainflags;
4634         uint32_t                chainlength;
4635         mptsas_cache_frames_t   *p;
4636 
4637         /*
4638          * Sgemax is the number of SGE's that will fit
4639          * each extra frame and frames is total
4640          * number of frames we'll need.  1 sge entry per
4641          * frame is reseverd for the chain element thus the -1 below.
4642          */
4643         sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_IEEE_SGE_SIMPLE64))
4644             - 1);
4645         temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
4646 
4647         /*
4648          * A little check to see if we need to round up the number
4649          * of frames we need
4650          */
4651         if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4652             sgemax) > 1) {
4653                 frames = (temp + 1);
4654         } else {
4655                 frames = temp;
4656         }
4657         NDBG1(("mptsas_ieee_sge_chain: temp=%d, frames=%d", temp, frames));
4658         dmap = cmd->cmd_sg;
4659         ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
4660 
4661         /*
4662          * First fill in the main frame
4663          */
4664         j = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
4665         mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl, j, 0);
4666         dmap += j;
4667         ieeesge += j;
4668         j++;
4669 
4670         /*
4671          * Fill in the chain element in the main frame.
4672          * About calculation on ChainOffset:
4673          * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4674          *    in the end reserved for SGL element storage
4675          *    (MPI2_SGE_IO_UNION); we should count it in our
4676          *    calculation.  See its definition in the header file.
4677          * 2. Constant j is the counter of the current SGL element
4678          *    that will be processed, and (j - 1) is the number of
4679          *    SGL elements that have been processed (stored in the
4680          *    main frame).
4681          * 3. ChainOffset value should be in units of quad-words (16
4682          *    bytes) so the last value should be divided by 16.
4683          */
4684         ddi_put8(acc_hdl, &frame->ChainOffset,
4685             (sizeof (MPI2_SCSI_IO_REQUEST) -
4686             sizeof (MPI2_SGE_IO_UNION) +
4687             (j - 1) * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
4688         ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
4689         chainflags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
4690             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4691         ddi_put8(acc_hdl, &ieeesgechain->Flags, chainflags);
4692 
4693         /*
4694          * The size of the next frame is the accurate size of space
4695          * (in bytes) used to store the SGL elements. j is the counter
4696          * of SGL elements. (j - 1) is the number of SGL elements that
4697          * have been processed (stored in frames).
4698          */
4699         if (frames >= 2) {
4700                 ASSERT(mpt->m_req_frame_size >=
4701                     sizeof (MPI2_IEEE_SGE_SIMPLE64));
4702                 chainlength = mpt->m_req_frame_size /
4703                     sizeof (MPI2_IEEE_SGE_SIMPLE64) *
4704                     sizeof (MPI2_IEEE_SGE_SIMPLE64);
4705         } else {
4706                 chainlength = ((cookiec - (j - 1)) *
4707                     sizeof (MPI2_IEEE_SGE_SIMPLE64));
4708         }
4709 
4710         p = cmd->cmd_extra_frames;
4711 
4712         ddi_put32(acc_hdl, &ieeesgechain->Length, chainlength);
4713         ddi_put32(acc_hdl, &ieeesgechain->Address.Low,
4714             p->m_phys_addr);
4715         /* SGL is allocated in the first 4G mem range */
4716         ddi_put32(acc_hdl, &ieeesgechain->Address.High, 0);
4717 
4718         /*
4719          * If there are more than 2 frames left we have to
4720          * fill in the next chain offset to the location of
4721          * the chain element in the next frame.
4722          * sgemax is the number of simple elements in an extra
4723          * frame. Note that the value NextChainOffset should be
4724          * in double-words (4 bytes).
4725          */
4726         if (frames >= 2) {
4727                 ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset,
4728                     (sgemax * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
4729         } else {
4730                 ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset, 0);
4731         }
4732 
4733         /*
4734          * Jump to next frame;
4735          * Starting here, chain buffers go into the per command SGL.
4736          * This buffer is allocated when chain buffers are needed.
4737          */
4738         ieeesge = (pMpi2IeeeSgeSimple64_t)p->m_frames_addr;
4739         i = cookiec;
4740 
4741         /*
4742          * Start filling in frames with SGE's.  If we
4743          * reach the end of frame and still have SGE's
4744          * to fill we need to add a chain element and
4745          * use another frame.  j will be our counter
4746          * for what cookie we are at and i will be
4747          * the total cookiec. k is the current frame
4748          */
4749         for (k = 1; k <= frames; k++) {
4750                 for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
4751 
4752                         /*
4753                          * If we have reached the end of frame
4754                          * and we have more SGE's to fill in
4755                          * we have to fill the final entry
4756                          * with a chain element and then
4757                          * continue to the next frame
4758                          */
4759                         if ((l == (sgemax + 1)) && (k != frames)) {
4760                                 ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
4761                                 j--;
4762                                 chainflags =
4763                                     MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
4764                                     MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
4765                                 ddi_put8(p->m_acc_hdl,
4766                                     &ieeesgechain->Flags, chainflags);
4767                                 /*
4768                                  * k is the frame counter and (k + 1)
4769                                  * is the number of the next frame.
4770                                  * Note that frames are in contiguous
4771                                  * memory space.
4772                                  */
4773                                 ddi_put32(p->m_acc_hdl,
4774                                     &ieeesgechain->Address.Low,
4775                                     (p->m_phys_addr +
4776                                     (mpt->m_req_frame_size * k)));
4777                                 ddi_put32(p->m_acc_hdl,
4778                                     &ieeesgechain->Address.High, 0);
4779 
4780                                 /*
4781                                  * If there are more than 2 frames left
4782                                  * we have to next chain offset to
4783                                  * the location of the chain element
4784                                  * in the next frame and fill in the
4785                                  * length of the next chain
4786                                  */
4787                                 if ((frames - k) >= 2) {
4788                                         ddi_put8(p->m_acc_hdl,
4789                                             &ieeesgechain->NextChainOffset,
4790                                             (sgemax *
4791                                             sizeof (MPI2_IEEE_SGE_SIMPLE64))
4792                                             >> 4);
4793                                         ASSERT(mpt->m_req_frame_size >=
4794                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4795                                         ddi_put32(p->m_acc_hdl,
4796                                             &ieeesgechain->Length,
4797                                             mpt->m_req_frame_size /
4798                                             sizeof (MPI2_IEEE_SGE_SIMPLE64) *
4799                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4800                                 } else {
4801                                         /*
4802                                          * This is the last frame. Set
4803                                          * the NextChainOffset to 0 and
4804                                          * Length is the total size of
4805                                          * all remaining simple elements
4806                                          */
4807                                         ddi_put8(p->m_acc_hdl,
4808                                             &ieeesgechain->NextChainOffset,
4809                                             0);
4810                                         ddi_put32(p->m_acc_hdl,
4811                                             &ieeesgechain->Length,
4812                                             (cookiec - j) *
4813                                             sizeof (MPI2_IEEE_SGE_SIMPLE64));
4814                                 }
4815 
4816                                 /* Jump to the next frame */
4817                                 ieeesge = (pMpi2IeeeSgeSimple64_t)
4818                                     ((char *)p->m_frames_addr +
4819                                     (int)mpt->m_req_frame_size * k);
4820 
4821                                 continue;
4822                         }
4823 
4824                         ddi_put32(p->m_acc_hdl,
4825                             &ieeesge->Address.Low,
4826                             dmap->addr.address64.Low);
4827                         ddi_put32(p->m_acc_hdl,
4828                             &ieeesge->Address.High,
4829                             dmap->addr.address64.High);
4830                         ddi_put32(p->m_acc_hdl,
4831                             &ieeesge->Length, dmap->count);
4832                         flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
4833                             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
4834 
4835                         /*
4836                          * If we are at the end of the frame and
4837                          * there is another frame to fill in
4838                          * do we need to do anything?
4839                          * if ((l == sgemax) && (k != frames)) {
4840                          * }
4841                          */
4842 
4843                         /*
4844                          * If this is the final cookie set end of list.
4845                          */
4846                         if (j == i) {
4847                                 flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
4848                         }
4849 
4850                         ddi_put8(p->m_acc_hdl, &ieeesge->Flags, flags);
4851                         dmap++;
4852                         ieeesge++;
4853                 }
4854         }
4855 
4856         /*
4857          * Sync DMA with the chain buffers that were just created
4858          */
4859         (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
4860 }
4861 
4862 static void
4863 mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4864     pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
4865 {
4866         ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
4867 
4868         NDBG1(("mptsas_sge_setup: cookiec=%d", cmd->cmd_cookiec));
4869 
4870         /*
4871          * Set read/write bit in control.
4872          */
4873         if (cmd->cmd_flags & CFLAG_DMASEND) {
4874                 *control |= MPI2_SCSIIO_CONTROL_WRITE;
4875         } else {
4876                 *control |= MPI2_SCSIIO_CONTROL_READ;
4877         }
4878 
4879         ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
4880 
4881         /*
4882          * We have 4 cases here.  First where we can fit all the
4883          * SG elements into the main frame, and the case
4884          * where we can't. The SG element is also different when using
4885          * MPI2.5 interface.
4886          * If we have more cookies than we can attach to a frame
4887          * we will need to use a chain element to point
4888          * a location of memory where the rest of the S/G
4889          * elements reside.
4890          */
4891         if (cmd->cmd_cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4892                 if (mpt->m_MPI25) {
4893                         mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl,
4894                             cmd->cmd_cookiec,
4895                             MPI25_IEEE_SGE_FLAGS_END_OF_LIST);
4896                 } else {
4897                         mptsas_sge_mainframe(cmd, frame, acc_hdl,
4898                             cmd->cmd_cookiec,
4899                             ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4900                             | MPI2_SGE_FLAGS_END_OF_BUFFER
4901                             | MPI2_SGE_FLAGS_END_OF_LIST) <<
4902                             MPI2_SGE_FLAGS_SHIFT));
4903                 }
4904         } else {
4905                 if (mpt->m_MPI25) {
4906                         mptsas_ieee_sge_chain(mpt, cmd, frame, acc_hdl);
4907                 } else {
4908                         mptsas_sge_chain(mpt, cmd, frame, acc_hdl);
4909                 }
4910         }
4911 }
4912 
4913 /*
4914  * Interrupt handling
4915  * Utility routine.  Poll for status of a command sent to HBA
4916  * without interrupts (a FLAG_NOINTR command).
4917  */
4918 int
4919 mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4920 {
4921         int     rval = TRUE;
4922 
4923         NDBG5(("mptsas_poll: cmd=0x%p", (void *)poll_cmd));
4924 
4925         if ((poll_cmd->cmd_flags & CFLAG_TM_CMD) == 0) {
4926                 mptsas_restart_hba(mpt);
4927         }
4928 
4929         /*
4930          * Wait, using drv_usecwait(), long enough for the command to
4931          * reasonably return from the target if the target isn't
4932          * "dead".  A polled command may well be sent from scsi_poll, and
4933          * there are retries built in to scsi_poll if the transport
4934          * accepted the packet (TRAN_ACCEPT).  scsi_poll waits 1 second
4935          * and retries the transport up to scsi_poll_busycnt times
4936          * (currently 60) if
4937          * 1. pkt_reason is CMD_INCOMPLETE and pkt_state is 0, or
4938          * 2. pkt_reason is CMD_CMPLT and *pkt_scbp has STATUS_BUSY
4939          *
4940          * limit the waiting to avoid a hang in the event that the
4941          * cmd never gets started but we are still receiving interrupts
4942          */
4943         while (!(poll_cmd->cmd_flags & CFLAG_FINISHED)) {
4944                 if (mptsas_wait_intr(mpt, polltime) == FALSE) {
4945                         NDBG5(("mptsas_poll: command incomplete"));
4946                         rval = FALSE;
4947                         break;
4948                 }
4949         }
4950 
4951         if (rval == FALSE) {
4952 
4953                 /*
4954                  * this isn't supposed to happen, the hba must be wedged
4955                  * Mark this cmd as a timeout.
4956                  */
4957                 mptsas_set_pkt_reason(mpt, poll_cmd, CMD_TIMEOUT,
4958                     (STAT_TIMEOUT|STAT_ABORTED));
4959 
4960                 if (poll_cmd->cmd_queued == FALSE) {
4961 
4962                         NDBG5(("mptsas_poll: not on waitq"));
4963 
4964                         poll_cmd->cmd_pkt->pkt_state |=
4965                             (STATE_GOT_BUS|STATE_GOT_TARGET|STATE_SENT_CMD);
4966                 } else {
4967 
4968                         /* find and remove it from the waitq */
4969                         NDBG5(("mptsas_poll: delete from waitq"));
4970                         mptsas_waitq_delete(mpt, poll_cmd);
4971                 }
4972 
4973         }
4974         mptsas_fma_check(mpt, poll_cmd);
4975         NDBG5(("mptsas_poll: done"));
4976         return (rval);
4977 }
4978 
4979 /*
4980  * Used for polling cmds and TM function
4981  */
4982 static int
4983 mptsas_wait_intr(mptsas_t *mpt, int polltime)
4984 {
4985         int                             cnt;
4986         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
4987         uint32_t                        int_mask;
4988 
4989         NDBG5(("mptsas_wait_intr"));
4990 
4991         mpt->m_polled_intr = 1;
4992 
4993         /*
4994          * Get the current interrupt mask and disable interrupts.  When
4995          * re-enabling ints, set mask to saved value.
4996          */
4997         int_mask = ddi_get32(mpt->m_datap, &mpt->m_reg->HostInterruptMask);
4998         MPTSAS_DISABLE_INTR(mpt);
4999 
5000         /*
5001          * Keep polling for at least (polltime * 1000) seconds
5002          */
5003         for (cnt = 0; cnt < polltime; cnt++) {
5004                 (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5005                     DDI_DMA_SYNC_FORCPU);
5006 
5007                 reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5008                     MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5009 
5010                 if (ddi_get32(mpt->m_acc_post_queue_hdl,
5011                     &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5012                     ddi_get32(mpt->m_acc_post_queue_hdl,
5013                     &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5014                         drv_usecwait(1000);
5015                         continue;
5016                 }
5017 
5018                 /*
5019                  * The reply is valid, process it according to its
5020                  * type.
5021                  */
5022                 mptsas_process_intr(mpt, reply_desc_union);
5023 
5024                 if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5025                         mpt->m_post_index = 0;
5026                 }
5027 
5028                 /*
5029                  * Update the global reply index
5030                  */
5031                 ddi_put32(mpt->m_datap,
5032                     &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5033                 mpt->m_polled_intr = 0;
5034 
5035                 /*
5036                  * Re-enable interrupts and quit.
5037                  */
5038                 ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask,
5039                     int_mask);
5040                 return (TRUE);
5041 
5042         }
5043 
5044         /*
5045          * Clear polling flag, re-enable interrupts and quit.
5046          */
5047         mpt->m_polled_intr = 0;
5048         ddi_put32(mpt->m_datap, &mpt->m_reg->HostInterruptMask, int_mask);
5049         return (FALSE);
5050 }
5051 
5052 static void
5053 mptsas_handle_scsi_io_success(mptsas_t *mpt,
5054     pMpi2ReplyDescriptorsUnion_t reply_desc)
5055 {
5056         pMpi2SCSIIOSuccessReplyDescriptor_t     scsi_io_success;
5057         uint16_t                                SMID;
5058         mptsas_slots_t                          *slots = mpt->m_active;
5059         mptsas_cmd_t                            *cmd = NULL;
5060         struct scsi_pkt                         *pkt;
5061 
5062         ASSERT(mutex_owned(&mpt->m_mutex));
5063 
5064         scsi_io_success = (pMpi2SCSIIOSuccessReplyDescriptor_t)reply_desc;
5065         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &scsi_io_success->SMID);
5066 
5067         /*
5068          * This is a success reply so just complete the IO.  First, do a sanity
5069          * check on the SMID.  The final slot is used for TM requests, which
5070          * would not come into this reply handler.
5071          */
5072         if ((SMID == 0) || (SMID > slots->m_n_normal)) {
5073                 mptsas_log(mpt, CE_WARN, "?Received invalid SMID of %d\n",
5074                     SMID);
5075                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5076                 return;
5077         }
5078 
5079         cmd = slots->m_slot[SMID];
5080 
5081         /*
5082          * print warning and return if the slot is empty
5083          */
5084         if (cmd == NULL) {
5085                 mptsas_log(mpt, CE_WARN, "?NULL command for successful SCSI IO "
5086                     "in slot %d", SMID);
5087                 return;
5088         }
5089 
5090         pkt = CMD2PKT(cmd);
5091         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
5092             STATE_GOT_STATUS);
5093         if (cmd->cmd_flags & CFLAG_DMAVALID) {
5094                 pkt->pkt_state |= STATE_XFERRED_DATA;
5095         }
5096         pkt->pkt_resid = 0;
5097 
5098         if (cmd->cmd_flags & CFLAG_PASSTHRU) {
5099                 cmd->cmd_flags |= CFLAG_FINISHED;
5100                 cv_broadcast(&mpt->m_passthru_cv);
5101                 return;
5102         } else {
5103                 mptsas_remove_cmd(mpt, cmd);
5104         }
5105 
5106         if (cmd->cmd_flags & CFLAG_RETRY) {
5107                 /*
5108                  * The target returned QFULL or busy, do not add tihs
5109                  * pkt to the doneq since the hba will retry
5110                  * this cmd.
5111                  *
5112                  * The pkt has already been resubmitted in
5113                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
5114                  * Remove this cmd_flag here.
5115                  */
5116                 cmd->cmd_flags &= ~CFLAG_RETRY;
5117         } else {
5118                 mptsas_doneq_add(mpt, cmd);
5119         }
5120 }
5121 
5122 static void
5123 mptsas_handle_address_reply(mptsas_t *mpt,
5124     pMpi2ReplyDescriptorsUnion_t reply_desc)
5125 {
5126         pMpi2AddressReplyDescriptor_t   address_reply;
5127         pMPI2DefaultReply_t             reply;
5128         mptsas_fw_diagnostic_buffer_t   *pBuffer;
5129         uint32_t                        reply_addr;
5130         uint16_t                        SMID, iocstatus;
5131         mptsas_slots_t                  *slots = mpt->m_active;
5132         mptsas_cmd_t                    *cmd = NULL;
5133         uint8_t                         function, buffer_type;
5134         m_replyh_arg_t                  *args;
5135         int                             reply_frame_no;
5136 
5137         ASSERT(mutex_owned(&mpt->m_mutex));
5138 
5139         address_reply = (pMpi2AddressReplyDescriptor_t)reply_desc;
5140         reply_addr = ddi_get32(mpt->m_acc_post_queue_hdl,
5141             &address_reply->ReplyFrameAddress);
5142         SMID = ddi_get16(mpt->m_acc_post_queue_hdl, &address_reply->SMID);
5143 
5144         /*
5145          * If reply frame is not in the proper range we should ignore this
5146          * message and exit the interrupt handler.
5147          */
5148         if ((reply_addr < mpt->m_reply_frame_dma_addr) ||
5149             (reply_addr >= (mpt->m_reply_frame_dma_addr +
5150             (mpt->m_reply_frame_size * mpt->m_max_replies))) ||
5151             ((reply_addr - mpt->m_reply_frame_dma_addr) %
5152             mpt->m_reply_frame_size != 0)) {
5153                 mptsas_log(mpt, CE_WARN, "?Received invalid reply frame "
5154                     "address 0x%x\n", reply_addr);
5155                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5156                 return;
5157         }
5158 
5159         (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
5160             DDI_DMA_SYNC_FORCPU);
5161         reply = (pMPI2DefaultReply_t)(mpt->m_reply_frame + (reply_addr -
5162             mpt->m_reply_frame_dma_addr));
5163         function = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->Function);
5164 
5165         NDBG31(("mptsas_handle_address_reply: function 0x%x, reply_addr=0x%x",
5166             function, reply_addr));
5167 
5168         /*
5169          * don't get slot information and command for events since these values
5170          * don't exist
5171          */
5172         if ((function != MPI2_FUNCTION_EVENT_NOTIFICATION) &&
5173             (function != MPI2_FUNCTION_DIAG_BUFFER_POST)) {
5174                 /*
5175                  * This could be a TM reply, which use the last allocated SMID,
5176                  * so allow for that.
5177                  */
5178                 if ((SMID == 0) || (SMID > (slots->m_n_normal + 1))) {
5179                         mptsas_log(mpt, CE_WARN, "?Received invalid SMID of "
5180                             "%d\n", SMID);
5181                         ddi_fm_service_impact(mpt->m_dip,
5182                             DDI_SERVICE_UNAFFECTED);
5183                         return;
5184                 }
5185 
5186                 cmd = slots->m_slot[SMID];
5187 
5188                 /*
5189                  * print warning and return if the slot is empty
5190                  */
5191                 if (cmd == NULL) {
5192                         mptsas_log(mpt, CE_WARN, "?NULL command for address "
5193                             "reply in slot %d", SMID);
5194                         return;
5195                 }
5196                 if ((cmd->cmd_flags &
5197                     (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
5198                         cmd->cmd_rfm = reply_addr;
5199                         cmd->cmd_flags |= CFLAG_FINISHED;
5200                         cv_broadcast(&mpt->m_passthru_cv);
5201                         cv_broadcast(&mpt->m_config_cv);
5202                         cv_broadcast(&mpt->m_fw_diag_cv);
5203                         return;
5204                 } else if (!(cmd->cmd_flags & CFLAG_FW_CMD)) {
5205                         mptsas_remove_cmd(mpt, cmd);
5206                 }
5207                 NDBG31(("\t\tmptsas_process_intr: slot=%d", SMID));
5208         }
5209         /*
5210          * Depending on the function, we need to handle
5211          * the reply frame (and cmd) differently.
5212          */
5213         switch (function) {
5214         case MPI2_FUNCTION_SCSI_IO_REQUEST:
5215                 mptsas_check_scsi_io_error(mpt, (pMpi2SCSIIOReply_t)reply, cmd);
5216                 break;
5217         case MPI2_FUNCTION_SCSI_TASK_MGMT:
5218                 cmd->cmd_rfm = reply_addr;
5219                 mptsas_check_task_mgt(mpt, (pMpi2SCSIManagementReply_t)reply,
5220                     cmd);
5221                 break;
5222         case MPI2_FUNCTION_FW_DOWNLOAD:
5223                 cmd->cmd_flags |= CFLAG_FINISHED;
5224                 cv_signal(&mpt->m_fw_cv);
5225                 break;
5226         case MPI2_FUNCTION_EVENT_NOTIFICATION:
5227                 reply_frame_no = (reply_addr - mpt->m_reply_frame_dma_addr) /
5228                     mpt->m_reply_frame_size;
5229                 args = &mpt->m_replyh_args[reply_frame_no];
5230                 args->mpt = (void *)mpt;
5231                 args->rfm = reply_addr;
5232 
5233                 /*
5234                  * Record the event if its type is enabled in
5235                  * this mpt instance by ioctl.
5236                  */
5237                 mptsas_record_event(args);
5238 
5239                 /*
5240                  * Handle time critical events
5241                  * NOT_RESPONDING/ADDED only now
5242                  */
5243                 if (mptsas_handle_event_sync(args) == DDI_SUCCESS) {
5244                         /*
5245                          * Would not return main process,
5246                          * just let taskq resolve ack action
5247                          * and ack would be sent in taskq thread
5248                          */
5249                         NDBG20(("send mptsas_handle_event_sync success"));
5250                 }
5251 
5252                 if (mpt->m_in_reset) {
5253                         NDBG20(("dropping event received during reset"));
5254                         return;
5255                 }
5256 
5257                 if ((ddi_taskq_dispatch(mpt->m_event_taskq, mptsas_handle_event,
5258                     (void *)args, DDI_NOSLEEP)) != DDI_SUCCESS) {
5259                         mptsas_log(mpt, CE_WARN, "No memory available"
5260                         "for dispatch taskq");
5261                         /*
5262                          * Return the reply frame to the free queue.
5263                          */
5264                         ddi_put32(mpt->m_acc_free_queue_hdl,
5265                             &((uint32_t *)(void *)
5266                             mpt->m_free_queue)[mpt->m_free_index], reply_addr);
5267                         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
5268                             DDI_DMA_SYNC_FORDEV);
5269                         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
5270                                 mpt->m_free_index = 0;
5271                         }
5272 
5273                         ddi_put32(mpt->m_datap,
5274                             &mpt->m_reg->ReplyFreeHostIndex, mpt->m_free_index);
5275                 }
5276                 return;
5277         case MPI2_FUNCTION_DIAG_BUFFER_POST:
5278                 /*
5279                  * If SMID is 0, this implies that the reply is due to a
5280                  * release function with a status that the buffer has been
5281                  * released.  Set the buffer flags accordingly.
5282                  */
5283                 if (SMID == 0) {
5284                         iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
5285                             &reply->IOCStatus);
5286                         buffer_type = ddi_get8(mpt->m_acc_reply_frame_hdl,
5287                             &(((pMpi2DiagBufferPostReply_t)reply)->BufferType));
5288                         if (iocstatus == MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED) {
5289                                 pBuffer =
5290                                     &mpt->m_fw_diag_buffer_list[buffer_type];
5291                                 pBuffer->valid_data = TRUE;
5292                                 pBuffer->owned_by_firmware = FALSE;
5293                                 pBuffer->immediate = FALSE;
5294                         }
5295                 } else {
5296                         /*
5297                          * Normal handling of diag post reply with SMID.
5298                          */
5299                         cmd = slots->m_slot[SMID];
5300 
5301                         /*
5302                          * print warning and return if the slot is empty
5303                          */
5304                         if (cmd == NULL) {
5305                                 mptsas_log(mpt, CE_WARN, "?NULL command for "
5306                                     "address reply in slot %d", SMID);
5307                                 return;
5308                         }
5309                         cmd->cmd_rfm = reply_addr;
5310                         cmd->cmd_flags |= CFLAG_FINISHED;
5311                         cv_broadcast(&mpt->m_fw_diag_cv);
5312                 }
5313                 return;
5314         default:
5315                 mptsas_log(mpt, CE_WARN, "Unknown function 0x%x ", function);
5316                 break;
5317         }
5318 
5319         /*
5320          * Return the reply frame to the free queue.
5321          */
5322         ddi_put32(mpt->m_acc_free_queue_hdl,
5323             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
5324             reply_addr);
5325         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
5326             DDI_DMA_SYNC_FORDEV);
5327         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
5328                 mpt->m_free_index = 0;
5329         }
5330         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
5331             mpt->m_free_index);
5332 
5333         if (cmd->cmd_flags & CFLAG_FW_CMD)
5334                 return;
5335 
5336         if (cmd->cmd_flags & CFLAG_RETRY) {
5337                 /*
5338                  * The target returned QFULL or busy, do not add this
5339                  * pkt to the doneq since the hba will retry
5340                  * this cmd.
5341                  *
5342                  * The pkt has already been resubmitted in
5343                  * mptsas_handle_qfull() or in mptsas_check_scsi_io_error().
5344                  * Remove this cmd_flag here.
5345                  */
5346                 cmd->cmd_flags &= ~CFLAG_RETRY;
5347         } else {
5348                 mptsas_doneq_add(mpt, cmd);
5349         }
5350 }
5351 
5352 static void
5353 mptsas_check_scsi_io_error(mptsas_t *mpt, pMpi2SCSIIOReply_t reply,
5354     mptsas_cmd_t *cmd)
5355 {
5356         uint8_t                 scsi_status, scsi_state;
5357         uint16_t                ioc_status;
5358         uint32_t                xferred, sensecount, responsedata, loginfo = 0;
5359         struct scsi_pkt         *pkt;
5360         struct scsi_arq_status  *arqstat;
5361         struct buf              *bp;
5362         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
5363         uint8_t                 *sensedata = NULL;
5364         uint64_t                sas_wwn;
5365         uint8_t                 phy;
5366         char                    wwn_str[MPTSAS_WWN_STRLEN];
5367 
5368         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
5369             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
5370                 bp = cmd->cmd_ext_arq_buf;
5371         } else {
5372                 bp = cmd->cmd_arq_buf;
5373         }
5374 
5375         scsi_status = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIStatus);
5376         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5377         scsi_state = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->SCSIState);
5378         xferred = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->TransferCount);
5379         sensecount = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->SenseCount);
5380         responsedata = ddi_get32(mpt->m_acc_reply_frame_hdl,
5381             &reply->ResponseInfo);
5382 
5383         if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
5384                 sas_wwn = ptgt->m_addr.mta_wwn;
5385                 phy = ptgt->m_phynum;
5386                 if (sas_wwn == 0) {
5387                         (void) sprintf(wwn_str, "p%x", phy);
5388                 } else {
5389                         (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
5390                 }
5391                 loginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
5392                     &reply->IOCLogInfo);
5393                 mptsas_log(mpt, CE_NOTE,
5394                     "?Log info 0x%x received for target %d %s.\n"
5395                     "\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5396                     loginfo, Tgt(cmd), wwn_str, scsi_status, ioc_status,
5397                     scsi_state);
5398         }
5399 
5400         NDBG31(("\t\tscsi_status=0x%x, ioc_status=0x%x, scsi_state=0x%x",
5401             scsi_status, ioc_status, scsi_state));
5402 
5403         pkt = CMD2PKT(cmd);
5404         *(pkt->pkt_scbp) = scsi_status;
5405 
5406         if (loginfo == 0x31170000) {
5407                 /*
5408                  * if loginfo PL_LOGINFO_CODE_IO_DEVICE_MISSING_DELAY_RETRY
5409                  * 0x31170000 comes, that means the device missing delay
5410                  * is in progressing, the command need retry later.
5411                  */
5412                 *(pkt->pkt_scbp) = STATUS_BUSY;
5413                 return;
5414         }
5415 
5416         if ((scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) &&
5417             ((ioc_status & MPI2_IOCSTATUS_MASK) ==
5418             MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE)) {
5419                 pkt->pkt_reason = CMD_INCOMPLETE;
5420                 pkt->pkt_state |= STATE_GOT_BUS;
5421                 if (ptgt->m_reset_delay == 0) {
5422                         mptsas_set_throttle(mpt, ptgt,
5423                             DRAIN_THROTTLE);
5424                 }
5425                 return;
5426         }
5427 
5428         if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
5429                 responsedata &= 0x000000FF;
5430                 if (responsedata & MPTSAS_SCSI_RESPONSE_CODE_TLR_OFF) {
5431                         mptsas_log(mpt, CE_NOTE, "Do not support the TLR\n");
5432                         pkt->pkt_reason = CMD_TLR_OFF;
5433                         return;
5434                 }
5435         }
5436 
5437 
5438         switch (scsi_status) {
5439         case MPI2_SCSI_STATUS_CHECK_CONDITION:
5440                 pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5441                 arqstat = (void*)(pkt->pkt_scbp);
5442                 arqstat->sts_rqpkt_status = *((struct scsi_status *)
5443                     (pkt->pkt_scbp));
5444                 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
5445                     STATE_SENT_CMD | STATE_GOT_STATUS | STATE_ARQ_DONE);
5446                 if (cmd->cmd_flags & CFLAG_XARQ) {
5447                         pkt->pkt_state |= STATE_XARQ_DONE;
5448                 }
5449                 if (pkt->pkt_resid != cmd->cmd_dmacount) {
5450                         pkt->pkt_state |= STATE_XFERRED_DATA;
5451                 }
5452                 arqstat->sts_rqpkt_reason = pkt->pkt_reason;
5453                 arqstat->sts_rqpkt_state  = pkt->pkt_state;
5454                 arqstat->sts_rqpkt_state |= STATE_XFERRED_DATA;
5455                 arqstat->sts_rqpkt_statistics = pkt->pkt_statistics;
5456                 sensedata = (uint8_t *)&arqstat->sts_sensedata;
5457 
5458                 bcopy((uchar_t *)bp->b_un.b_addr, sensedata,
5459                     ((cmd->cmd_rqslen >= sensecount) ? sensecount :
5460                     cmd->cmd_rqslen));
5461                 arqstat->sts_rqpkt_resid = (cmd->cmd_rqslen - sensecount);
5462                 cmd->cmd_flags |= CFLAG_CMDARQ;
5463                 /*
5464                  * Set proper status for pkt if autosense was valid
5465                  */
5466                 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
5467                         struct scsi_status zero_status = { 0 };
5468                         arqstat->sts_rqpkt_status = zero_status;
5469                 }
5470 
5471                 /*
5472                  * ASC=0x47 is parity error
5473                  * ASC=0x48 is initiator detected error received
5474                  */
5475                 if ((scsi_sense_key(sensedata) == KEY_ABORTED_COMMAND) &&
5476                     ((scsi_sense_asc(sensedata) == 0x47) ||
5477                     (scsi_sense_asc(sensedata) == 0x48))) {
5478                         mptsas_log(mpt, CE_NOTE, "Aborted_command!");
5479                 }
5480 
5481                 /*
5482                  * ASC/ASCQ=0x3F/0x0E means report_luns data changed
5483                  * ASC/ASCQ=0x25/0x00 means invalid lun
5484                  */
5485                 if (((scsi_sense_key(sensedata) == KEY_UNIT_ATTENTION) &&
5486                     (scsi_sense_asc(sensedata) == 0x3F) &&
5487                     (scsi_sense_ascq(sensedata) == 0x0E)) ||
5488                     ((scsi_sense_key(sensedata) == KEY_ILLEGAL_REQUEST) &&
5489                     (scsi_sense_asc(sensedata) == 0x25) &&
5490                     (scsi_sense_ascq(sensedata) == 0x00))) {
5491                         mptsas_topo_change_list_t *topo_node = NULL;
5492 
5493                         topo_node = kmem_zalloc(
5494                             sizeof (mptsas_topo_change_list_t),
5495                             KM_NOSLEEP);
5496                         if (topo_node == NULL) {
5497                                 mptsas_log(mpt, CE_NOTE, "No memory"
5498                                     "resource for handle SAS dynamic"
5499                                     "reconfigure.\n");
5500                                 break;
5501                         }
5502                         topo_node->mpt = mpt;
5503                         topo_node->event = MPTSAS_DR_EVENT_RECONFIG_TARGET;
5504                         topo_node->un.phymask = ptgt->m_addr.mta_phymask;
5505                         topo_node->devhdl = ptgt->m_devhdl;
5506                         topo_node->object = (void *)ptgt;
5507                         topo_node->flags = MPTSAS_TOPO_FLAG_LUN_ASSOCIATED;
5508 
5509                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
5510                             mptsas_handle_dr,
5511                             (void *)topo_node,
5512                             DDI_NOSLEEP)) != DDI_SUCCESS) {
5513                                 kmem_free(topo_node,
5514                                     sizeof (mptsas_topo_change_list_t));
5515                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq"
5516                                     "for handle SAS dynamic reconfigure"
5517                                     "failed. \n");
5518                         }
5519                 }
5520                 break;
5521         case MPI2_SCSI_STATUS_GOOD:
5522                 switch (ioc_status & MPI2_IOCSTATUS_MASK) {
5523                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
5524                         pkt->pkt_reason = CMD_DEV_GONE;
5525                         pkt->pkt_state |= STATE_GOT_BUS;
5526                         if (ptgt->m_reset_delay == 0) {
5527                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5528                         }
5529                         NDBG31(("lost disk for target%d, command:%x",
5530                             Tgt(cmd), pkt->pkt_cdbp[0]));
5531                         break;
5532                 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
5533                         NDBG31(("data overrun: xferred=%d", xferred));
5534                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5535                         pkt->pkt_reason = CMD_DATA_OVR;
5536                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5537                             | STATE_SENT_CMD | STATE_GOT_STATUS
5538                             | STATE_XFERRED_DATA);
5539                         pkt->pkt_resid = 0;
5540                         break;
5541                 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
5542                 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
5543                         NDBG31(("data underrun: xferred=%d", xferred));
5544                         NDBG31(("dmacount=%d", cmd->cmd_dmacount));
5545                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET
5546                             | STATE_SENT_CMD | STATE_GOT_STATUS);
5547                         pkt->pkt_resid = (cmd->cmd_dmacount - xferred);
5548                         if (pkt->pkt_resid != cmd->cmd_dmacount) {
5549                                 pkt->pkt_state |= STATE_XFERRED_DATA;
5550                         }
5551                         break;
5552                 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
5553                         if (cmd->cmd_active_expiration <= gethrtime()) {
5554                                 /*
5555                                  * When timeout requested, propagate
5556                                  * proper reason and statistics to
5557                                  * target drivers.
5558                                  */
5559                                 mptsas_set_pkt_reason(mpt, cmd, CMD_TIMEOUT,
5560                                     STAT_BUS_RESET | STAT_TIMEOUT);
5561                         } else {
5562                                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
5563                                     STAT_BUS_RESET);
5564                         }
5565                         break;
5566                 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
5567                 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
5568                         mptsas_set_pkt_reason(mpt,
5569                             cmd, CMD_RESET, STAT_DEV_RESET);
5570                         break;
5571                 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
5572                 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
5573                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
5574                         mptsas_set_pkt_reason(mpt,
5575                             cmd, CMD_TERMINATED, STAT_TERMINATED);
5576                         break;
5577                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
5578                 case MPI2_IOCSTATUS_BUSY:
5579                         /*
5580                          * set throttles to drain
5581                          */
5582                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
5583                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
5584                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5585                         }
5586 
5587                         /*
5588                          * retry command
5589                          */
5590                         cmd->cmd_flags |= CFLAG_RETRY;
5591                         cmd->cmd_pkt_flags |= FLAG_HEAD;
5592 
5593                         (void) mptsas_accept_pkt(mpt, cmd);
5594                         break;
5595                 default:
5596                         mptsas_log(mpt, CE_WARN,
5597                             "unknown ioc_status = %x\n", ioc_status);
5598                         mptsas_log(mpt, CE_CONT, "scsi_state = %x, transfer "
5599                             "count = %x, scsi_status = %x", scsi_state,
5600                             xferred, scsi_status);
5601                         break;
5602                 }
5603                 break;
5604         case MPI2_SCSI_STATUS_TASK_SET_FULL:
5605                 mptsas_handle_qfull(mpt, cmd);
5606                 break;
5607         case MPI2_SCSI_STATUS_BUSY:
5608                 NDBG31(("scsi_status busy received"));
5609                 break;
5610         case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
5611                 NDBG31(("scsi_status reservation conflict received"));
5612                 break;
5613         default:
5614                 mptsas_log(mpt, CE_WARN, "scsi_status=%x, ioc_status=%x\n",
5615                     scsi_status, ioc_status);
5616                 mptsas_log(mpt, CE_WARN,
5617                     "mptsas_process_intr: invalid scsi status\n");
5618                 break;
5619         }
5620 }
5621 
5622 static void
5623 mptsas_check_task_mgt(mptsas_t *mpt, pMpi2SCSIManagementReply_t reply,
5624         mptsas_cmd_t *cmd)
5625 {
5626         uint8_t         task_type;
5627         uint16_t        ioc_status;
5628         uint32_t        log_info;
5629         uint16_t        dev_handle;
5630         struct scsi_pkt *pkt = CMD2PKT(cmd);
5631 
5632         task_type = ddi_get8(mpt->m_acc_reply_frame_hdl, &reply->TaskType);
5633         ioc_status = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->IOCStatus);
5634         log_info = ddi_get32(mpt->m_acc_reply_frame_hdl, &reply->IOCLogInfo);
5635         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl, &reply->DevHandle);
5636 
5637         if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5638                 mptsas_log(mpt, CE_WARN, "mptsas_check_task_mgt: Task 0x%x "
5639                     "failed. IOCStatus=0x%x IOCLogInfo=0x%x target=%d\n",
5640                     task_type, ioc_status, log_info, dev_handle);
5641                 pkt->pkt_reason = CMD_INCOMPLETE;
5642                 return;
5643         }
5644 
5645         switch (task_type) {
5646         case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
5647         case MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET:
5648         case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
5649         case MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA:
5650         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET:
5651         case MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION:
5652                 break;
5653         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
5654         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
5655         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
5656                 /*
5657                  * Check for invalid DevHandle of 0 in case application
5658                  * sends bad command.  DevHandle of 0 could cause problems.
5659                  */
5660                 if (dev_handle == 0) {
5661                         mptsas_log(mpt, CE_WARN, "!Can't flush target with"
5662                             " DevHandle of 0.");
5663                 } else {
5664                         mptsas_flush_target(mpt, dev_handle, Lun(cmd),
5665                             task_type);
5666                 }
5667                 break;
5668         default:
5669                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
5670                     task_type);
5671                 mptsas_log(mpt, CE_WARN, "ioc status = %x", ioc_status);
5672                 break;
5673         }
5674 }
5675 
5676 static void
5677 mptsas_doneq_thread(mptsas_doneq_thread_arg_t *arg)
5678 {
5679         mptsas_t                        *mpt = arg->mpt;
5680         uint64_t                        t = arg->t;
5681         mptsas_cmd_t                    *cmd;
5682         struct scsi_pkt                 *pkt;
5683         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
5684 
5685         mutex_enter(&item->mutex);
5686         while (item->flag & MPTSAS_DONEQ_THREAD_ACTIVE) {
5687                 if (!item->doneq) {
5688                         cv_wait(&item->cv, &item->mutex);
5689                 }
5690                 pkt = NULL;
5691                 if ((cmd = mptsas_doneq_thread_rm(mpt, t)) != NULL) {
5692                         cmd->cmd_flags |= CFLAG_COMPLETED;
5693                         pkt = CMD2PKT(cmd);
5694                 }
5695                 mutex_exit(&item->mutex);
5696                 if (pkt) {
5697                         mptsas_pkt_comp(pkt, cmd);
5698                 }
5699                 mutex_enter(&item->mutex);
5700         }
5701         mutex_exit(&item->mutex);
5702         mutex_enter(&mpt->m_doneq_mutex);
5703         mpt->m_doneq_thread_n--;
5704         cv_broadcast(&mpt->m_doneq_thread_cv);
5705         mutex_exit(&mpt->m_doneq_mutex);
5706 }
5707 
5708 
5709 /*
5710  * mpt interrupt handler.
5711  */
5712 static uint_t
5713 mptsas_intr(caddr_t arg1, caddr_t arg2)
5714 {
5715         mptsas_t                        *mpt = (void *)arg1;
5716         pMpi2ReplyDescriptorsUnion_t    reply_desc_union;
5717         uchar_t                         did_reply = FALSE;
5718 
5719         NDBG1(("mptsas_intr: arg1 0x%p arg2 0x%p", (void *)arg1, (void *)arg2));
5720 
5721         mutex_enter(&mpt->m_mutex);
5722 
5723         /*
5724          * If interrupts are shared by two channels then check whether this
5725          * interrupt is genuinely for this channel by making sure first the
5726          * chip is in high power state.
5727          */
5728         if ((mpt->m_options & MPTSAS_OPT_PM) &&
5729             (mpt->m_power_level != PM_LEVEL_D0)) {
5730                 mutex_exit(&mpt->m_mutex);
5731                 return (DDI_INTR_UNCLAIMED);
5732         }
5733 
5734         /*
5735          * If polling, interrupt was triggered by some shared interrupt because
5736          * IOC interrupts are disabled during polling, so polling routine will
5737          * handle any replies.  Considering this, if polling is happening,
5738          * return with interrupt unclaimed.
5739          */
5740         if (mpt->m_polled_intr) {
5741                 mutex_exit(&mpt->m_mutex);
5742                 mptsas_log(mpt, CE_WARN, "mpt_sas: Unclaimed interrupt");
5743                 return (DDI_INTR_UNCLAIMED);
5744         }
5745 
5746         /*
5747          * Read the istat register.
5748          */
5749         if ((INTPENDING(mpt)) != 0) {
5750                 /*
5751                  * read fifo until empty.
5752                  */
5753 #ifndef __lock_lint
5754                 _NOTE(CONSTCOND)
5755 #endif
5756                 while (TRUE) {
5757                         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5758                             DDI_DMA_SYNC_FORCPU);
5759                         reply_desc_union = (pMpi2ReplyDescriptorsUnion_t)
5760                             MPTSAS_GET_NEXT_REPLY(mpt, mpt->m_post_index);
5761 
5762                         if (ddi_get32(mpt->m_acc_post_queue_hdl,
5763                             &reply_desc_union->Words.Low) == 0xFFFFFFFF ||
5764                             ddi_get32(mpt->m_acc_post_queue_hdl,
5765                             &reply_desc_union->Words.High) == 0xFFFFFFFF) {
5766                                 break;
5767                         }
5768 
5769                         /*
5770                          * The reply is valid, process it according to its
5771                          * type.  Also, set a flag for updating the reply index
5772                          * after they've all been processed.
5773                          */
5774                         did_reply = TRUE;
5775 
5776                         mptsas_process_intr(mpt, reply_desc_union);
5777 
5778                         /*
5779                          * Increment post index and roll over if needed.
5780                          */
5781                         if (++mpt->m_post_index == mpt->m_post_queue_depth) {
5782                                 mpt->m_post_index = 0;
5783                         }
5784                 }
5785 
5786                 /*
5787                  * Update the global reply index if at least one reply was
5788                  * processed.
5789                  */
5790                 if (did_reply) {
5791                         ddi_put32(mpt->m_datap,
5792                             &mpt->m_reg->ReplyPostHostIndex, mpt->m_post_index);
5793                 }
5794         } else {
5795                 mutex_exit(&mpt->m_mutex);
5796                 return (DDI_INTR_UNCLAIMED);
5797         }
5798         NDBG1(("mptsas_intr complete"));
5799 
5800         /*
5801          * If no helper threads are created, process the doneq in ISR. If
5802          * helpers are created, use the doneq length as a metric to measure the
5803          * load on the interrupt CPU. If it is long enough, which indicates the
5804          * load is heavy, then we deliver the IO completions to the helpers.
5805          * This measurement has some limitations, although it is simple and
5806          * straightforward and works well for most of the cases at present.
5807          */
5808         if (!mpt->m_doneq_thread_n ||
5809             (mpt->m_doneq_len <= mpt->m_doneq_length_threshold)) {
5810                 mptsas_doneq_empty(mpt);
5811         } else {
5812                 mptsas_deliver_doneq_thread(mpt);
5813         }
5814 
5815         /*
5816          * If there are queued cmd, start them now.
5817          */
5818         if (mpt->m_waitq != NULL) {
5819                 mptsas_restart_waitq(mpt);
5820         }
5821 
5822         mutex_exit(&mpt->m_mutex);
5823         return (DDI_INTR_CLAIMED);
5824 }
5825 
5826 static void
5827 mptsas_process_intr(mptsas_t *mpt,
5828     pMpi2ReplyDescriptorsUnion_t reply_desc_union)
5829 {
5830         uint8_t reply_type;
5831 
5832         ASSERT(mutex_owned(&mpt->m_mutex));
5833 
5834         /*
5835          * The reply is valid, process it according to its
5836          * type.  Also, set a flag for updated the reply index
5837          * after they've all been processed.
5838          */
5839         reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5840             &reply_desc_union->Default.ReplyFlags);
5841         reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5842         if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS ||
5843             reply_type == MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS) {
5844                 mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5845         } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5846                 mptsas_handle_address_reply(mpt, reply_desc_union);
5847         } else {
5848                 mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5849                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5850         }
5851 
5852         /*
5853          * Clear the reply descriptor for re-use and increment
5854          * index.
5855          */
5856         ddi_put64(mpt->m_acc_post_queue_hdl,
5857             &((uint64_t *)(void *)mpt->m_post_queue)[mpt->m_post_index],
5858             0xFFFFFFFFFFFFFFFF);
5859         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
5860             DDI_DMA_SYNC_FORDEV);
5861 }
5862 
5863 /*
5864  * handle qfull condition
5865  */
5866 static void
5867 mptsas_handle_qfull(mptsas_t *mpt, mptsas_cmd_t *cmd)
5868 {
5869         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
5870 
5871         if ((++cmd->cmd_qfull_retries > ptgt->m_qfull_retries) ||
5872             (ptgt->m_qfull_retries == 0)) {
5873                 /*
5874                  * We have exhausted the retries on QFULL, or,
5875                  * the target driver has indicated that it
5876                  * wants to handle QFULL itself by setting
5877                  * qfull-retries capability to 0. In either case
5878                  * we want the target driver's QFULL handling
5879                  * to kick in. We do this by having pkt_reason
5880                  * as CMD_CMPLT and pkt_scbp as STATUS_QFULL.
5881                  */
5882                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
5883         } else {
5884                 if (ptgt->m_reset_delay == 0) {
5885                         ptgt->m_t_throttle =
5886                             max((ptgt->m_t_ncmds - 2), 0);
5887                 }
5888 
5889                 cmd->cmd_pkt_flags |= FLAG_HEAD;
5890                 cmd->cmd_flags &= ~(CFLAG_TRANFLAG);
5891                 cmd->cmd_flags |= CFLAG_RETRY;
5892 
5893                 (void) mptsas_accept_pkt(mpt, cmd);
5894 
5895                 /*
5896                  * when target gives queue full status with no commands
5897                  * outstanding (m_t_ncmds == 0), throttle is set to 0
5898                  * (HOLD_THROTTLE), and the queue full handling start
5899                  * (see psarc/1994/313); if there are commands outstanding,
5900                  * throttle is set to (m_t_ncmds - 2)
5901                  */
5902                 if (ptgt->m_t_throttle == HOLD_THROTTLE) {
5903                         /*
5904                          * By setting throttle to QFULL_THROTTLE, we
5905                          * avoid submitting new commands and in
5906                          * mptsas_restart_cmd find out slots which need
5907                          * their throttles to be cleared.
5908                          */
5909                         mptsas_set_throttle(mpt, ptgt, QFULL_THROTTLE);
5910                         if (mpt->m_restart_cmd_timeid == 0) {
5911                                 mpt->m_restart_cmd_timeid =
5912                                     timeout(mptsas_restart_cmd, mpt,
5913                                     ptgt->m_qfull_retry_interval);
5914                         }
5915                 }
5916         }
5917 }
5918 
5919 mptsas_phymask_t
5920 mptsas_physport_to_phymask(mptsas_t *mpt, uint8_t physport)
5921 {
5922         mptsas_phymask_t        phy_mask = 0;
5923         uint8_t                 i = 0;
5924 
5925         NDBG20(("mptsas%d physport_to_phymask enter", mpt->m_instance));
5926 
5927         ASSERT(mutex_owned(&mpt->m_mutex));
5928 
5929         /*
5930          * If physport is 0xFF, this is a RAID volume.  Use phymask of 0.
5931          */
5932         if (physport == 0xFF) {
5933                 return (0);
5934         }
5935 
5936         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
5937                 if (mpt->m_phy_info[i].attached_devhdl &&
5938                     (mpt->m_phy_info[i].phy_mask != 0) &&
5939                     (mpt->m_phy_info[i].port_num == physport)) {
5940                         phy_mask = mpt->m_phy_info[i].phy_mask;
5941                         break;
5942                 }
5943         }
5944         NDBG20(("mptsas%d physport_to_phymask:physport :%x phymask :%x, ",
5945             mpt->m_instance, physport, phy_mask));
5946         return (phy_mask);
5947 }
5948 
5949 /*
5950  * mpt free device handle after device gone, by use of passthrough
5951  */
5952 static int
5953 mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl)
5954 {
5955         Mpi2SasIoUnitControlRequest_t   req;
5956         Mpi2SasIoUnitControlReply_t     rep;
5957         int                             ret;
5958 
5959         ASSERT(mutex_owned(&mpt->m_mutex));
5960 
5961         /*
5962          * Need to compose a SAS IO Unit Control request message
5963          * and call mptsas_do_passthru() function
5964          */
5965         bzero(&req, sizeof (req));
5966         bzero(&rep, sizeof (rep));
5967 
5968         req.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
5969         req.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
5970         req.DevHandle = LE_16(devhdl);
5971 
5972         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
5973             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
5974         if (ret != 0) {
5975                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5976                     "Control error %d", ret);
5977                 return (DDI_FAILURE);
5978         }
5979 
5980         /* do passthrough success, check the ioc status */
5981         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
5982                 cmn_err(CE_WARN, "mptsas_free_devhdl: passthru SAS IO Unit "
5983                     "Control IOCStatus %d", LE_16(rep.IOCStatus));
5984                 return (DDI_FAILURE);
5985         }
5986 
5987         return (DDI_SUCCESS);
5988 }
5989 
5990 static void
5991 mptsas_update_phymask(mptsas_t *mpt)
5992 {
5993         mptsas_phymask_t mask = 0, phy_mask;
5994         char            *phy_mask_name;
5995         uint8_t         current_port;
5996         int             i, j;
5997 
5998         NDBG20(("mptsas%d update phymask ", mpt->m_instance));
5999 
6000         ASSERT(mutex_owned(&mpt->m_mutex));
6001 
6002         (void) mptsas_get_sas_io_unit_page(mpt);
6003 
6004         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6005 
6006         for (i = 0; i < mpt->m_num_phys; i++) {
6007                 phy_mask = 0x00;
6008 
6009                 if (mpt->m_phy_info[i].attached_devhdl == 0)
6010                         continue;
6011 
6012                 bzero(phy_mask_name, sizeof (phy_mask_name));
6013 
6014                 current_port = mpt->m_phy_info[i].port_num;
6015 
6016                 if ((mask & (1 << i)) != 0)
6017                         continue;
6018 
6019                 for (j = 0; j < mpt->m_num_phys; j++) {
6020                         if (mpt->m_phy_info[j].attached_devhdl &&
6021                             (mpt->m_phy_info[j].port_num == current_port)) {
6022                                 phy_mask |= (1 << j);
6023                         }
6024                 }
6025                 mask = mask | phy_mask;
6026 
6027                 for (j = 0; j < mpt->m_num_phys; j++) {
6028                         if ((phy_mask >> j) & 0x01) {
6029                                 mpt->m_phy_info[j].phy_mask = phy_mask;
6030                         }
6031                 }
6032 
6033                 (void) sprintf(phy_mask_name, "%x", phy_mask);
6034 
6035                 mutex_exit(&mpt->m_mutex);
6036                 /*
6037                  * register a iport, if the port has already been existed
6038                  * SCSA will do nothing and just return.
6039                  */
6040                 (void) scsi_hba_iport_register(mpt->m_dip, phy_mask_name);
6041                 mutex_enter(&mpt->m_mutex);
6042         }
6043         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6044         NDBG20(("mptsas%d update phymask return", mpt->m_instance));
6045 }
6046 
6047 /*
6048  * mptsas_handle_dr is a task handler for DR, the DR action includes:
6049  * 1. Directly attched Device Added/Removed.
6050  * 2. Expander Device Added/Removed.
6051  * 3. Indirectly Attached Device Added/Expander.
6052  * 4. LUNs of a existing device status change.
6053  * 5. RAID volume created/deleted.
6054  * 6. Member of RAID volume is released because of RAID deletion.
6055  * 7. Physical disks are removed because of RAID creation.
6056  */
6057 static void
6058 mptsas_handle_dr(void *args) {
6059         mptsas_topo_change_list_t       *topo_node = NULL;
6060         mptsas_topo_change_list_t       *save_node = NULL;
6061         mptsas_t                        *mpt;
6062         dev_info_t                      *parent = NULL;
6063         mptsas_phymask_t                phymask = 0;
6064         char                            *phy_mask_name;
6065         uint8_t                         flags = 0, physport = 0xff;
6066         uint8_t                         port_update = 0;
6067         uint_t                          event;
6068 
6069         topo_node = (mptsas_topo_change_list_t *)args;
6070 
6071         mpt = topo_node->mpt;
6072         event = topo_node->event;
6073         flags = topo_node->flags;
6074 
6075         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6076 
6077         NDBG20(("mptsas%d handle_dr enter", mpt->m_instance));
6078 
6079         switch (event) {
6080         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6081                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6082                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE) ||
6083                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6084                         /*
6085                          * Direct attached or expander attached device added
6086                          * into system or a Phys Disk that is being unhidden.
6087                          */
6088                         port_update = 1;
6089                 }
6090                 break;
6091         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6092                 /*
6093                  * New expander added into system, it must be the head
6094                  * of topo_change_list_t
6095                  */
6096                 port_update = 1;
6097                 break;
6098         default:
6099                 port_update = 0;
6100                 break;
6101         }
6102         /*
6103          * All cases port_update == 1 may cause initiator port form change
6104          */
6105         mutex_enter(&mpt->m_mutex);
6106         if (mpt->m_port_chng && port_update) {
6107                 /*
6108                  * mpt->m_port_chng flag indicates some PHYs of initiator
6109                  * port have changed to online. So when expander added or
6110                  * directly attached device online event come, we force to
6111                  * update port information by issueing SAS IO Unit Page and
6112                  * update PHYMASKs.
6113                  */
6114                 (void) mptsas_update_phymask(mpt);
6115                 mpt->m_port_chng = 0;
6116 
6117         }
6118         mutex_exit(&mpt->m_mutex);
6119         while (topo_node) {
6120                 phymask = 0;
6121                 if (parent == NULL) {
6122                         physport = topo_node->un.physport;
6123                         event = topo_node->event;
6124                         flags = topo_node->flags;
6125                         if (event & (MPTSAS_DR_EVENT_OFFLINE_TARGET |
6126                             MPTSAS_DR_EVENT_OFFLINE_SMP)) {
6127                                 /*
6128                                  * For all offline events, phymask is known
6129                                  */
6130                                 phymask = topo_node->un.phymask;
6131                                 goto find_parent;
6132                         }
6133                         if (event & MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6134                                 goto handle_topo_change;
6135                         }
6136                         if (flags & MPTSAS_TOPO_FLAG_LUN_ASSOCIATED) {
6137                                 phymask = topo_node->un.phymask;
6138                                 goto find_parent;
6139                         }
6140 
6141                         if ((flags ==
6142                             MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) &&
6143                             (event == MPTSAS_DR_EVENT_RECONFIG_TARGET)) {
6144                                 /*
6145                                  * There is no any field in IR_CONFIG_CHANGE
6146                                  * event indicate physport/phynum, let's get
6147                                  * parent after SAS Device Page0 request.
6148                                  */
6149                                 goto handle_topo_change;
6150                         }
6151 
6152                         mutex_enter(&mpt->m_mutex);
6153                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6154                                 /*
6155                                  * If the direct attached device added or a
6156                                  * phys disk is being unhidden, argument
6157                                  * physport actually is PHY#, so we have to get
6158                                  * phymask according PHY#.
6159                                  */
6160                                 physport = mpt->m_phy_info[physport].port_num;
6161                         }
6162 
6163                         /*
6164                          * Translate physport to phymask so that we can search
6165                          * parent dip.
6166                          */
6167                         phymask = mptsas_physport_to_phymask(mpt,
6168                             physport);
6169                         mutex_exit(&mpt->m_mutex);
6170 
6171 find_parent:
6172                         bzero(phy_mask_name, MPTSAS_MAX_PHYS);
6173                         /*
6174                          * For RAID topology change node, write the iport name
6175                          * as v0.
6176                          */
6177                         if (flags & MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6178                                 (void) sprintf(phy_mask_name, "v0");
6179                         } else {
6180                                 /*
6181                                  * phymask can bo 0 if the drive has been
6182                                  * pulled by the time an add event is
6183                                  * processed.  If phymask is 0, just skip this
6184                                  * event and continue.
6185                                  */
6186                                 if (phymask == 0) {
6187                                         mutex_enter(&mpt->m_mutex);
6188                                         save_node = topo_node;
6189                                         topo_node = topo_node->next;
6190                                         ASSERT(save_node);
6191                                         kmem_free(save_node,
6192                                             sizeof (mptsas_topo_change_list_t));
6193                                         mutex_exit(&mpt->m_mutex);
6194 
6195                                         parent = NULL;
6196                                         continue;
6197                                 }
6198                                 (void) sprintf(phy_mask_name, "%x", phymask);
6199                         }
6200                         parent = scsi_hba_iport_find(mpt->m_dip,
6201                             phy_mask_name);
6202                         if (parent == NULL) {
6203                                 mptsas_log(mpt, CE_WARN, "Failed to find an "
6204                                     "iport, should not happen!");
6205                                 goto out;
6206                         }
6207 
6208                 }
6209                 ASSERT(parent);
6210 handle_topo_change:
6211 
6212                 mutex_enter(&mpt->m_mutex);
6213                 /*
6214                  * If HBA is being reset, don't perform operations depending
6215                  * on the IOC. We must free the topo list, however.
6216                  */
6217                 if (!mpt->m_in_reset)
6218                         mptsas_handle_topo_change(topo_node, parent);
6219                 else
6220                         NDBG20(("skipping topo change received during reset"));
6221                 save_node = topo_node;
6222                 topo_node = topo_node->next;
6223                 ASSERT(save_node);
6224                 kmem_free(save_node, sizeof (mptsas_topo_change_list_t));
6225                 mutex_exit(&mpt->m_mutex);
6226 
6227                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6228                     (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) ||
6229                     (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED)) {
6230                         /*
6231                          * If direct attached device associated, make sure
6232                          * reset the parent before start the next one. But
6233                          * all devices associated with expander shares the
6234                          * parent.  Also, reset parent if this is for RAID.
6235                          */
6236                         parent = NULL;
6237                 }
6238         }
6239 out:
6240         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6241 }
6242 
6243 static void
6244 mptsas_handle_topo_change(mptsas_topo_change_list_t *topo_node,
6245     dev_info_t *parent)
6246 {
6247         mptsas_target_t *ptgt = NULL;
6248         mptsas_smp_t    *psmp = NULL;
6249         mptsas_t        *mpt = (void *)topo_node->mpt;
6250         uint16_t        devhdl;
6251         uint16_t        attached_devhdl;
6252         uint64_t        sas_wwn = 0;
6253         int             rval = 0;
6254         uint32_t        page_address;
6255         uint8_t         phy, flags;
6256         char            *addr = NULL;
6257         dev_info_t      *lundip;
6258         int             circ = 0, circ1 = 0;
6259         char            attached_wwnstr[MPTSAS_WWN_STRLEN];
6260 
6261         NDBG20(("mptsas%d handle_topo_change enter, devhdl 0x%x,"
6262             "event 0x%x, flags 0x%x", mpt->m_instance, topo_node->devhdl,
6263             topo_node->event, topo_node->flags));
6264 
6265         ASSERT(mutex_owned(&mpt->m_mutex));
6266 
6267         switch (topo_node->event) {
6268         case MPTSAS_DR_EVENT_RECONFIG_TARGET:
6269         {
6270                 char *phy_mask_name;
6271                 mptsas_phymask_t phymask = 0;
6272 
6273                 if (topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6274                         /*
6275                          * Get latest RAID info.
6276                          */
6277                         (void) mptsas_get_raid_info(mpt);
6278                         ptgt = refhash_linear_search(mpt->m_targets,
6279                             mptsas_target_eval_devhdl, &topo_node->devhdl);
6280                         if (ptgt == NULL)
6281                                 break;
6282                 } else {
6283                         ptgt = (void *)topo_node->object;
6284                 }
6285 
6286                 if (ptgt == NULL) {
6287                         /*
6288                          * If a Phys Disk was deleted, RAID info needs to be
6289                          * updated to reflect the new topology.
6290                          */
6291                         (void) mptsas_get_raid_info(mpt);
6292 
6293                         /*
6294                          * Get sas device page 0 by DevHandle to make sure if
6295                          * SSP/SATA end device exist.
6296                          */
6297                         page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
6298                             MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
6299                             topo_node->devhdl;
6300 
6301                         rval = mptsas_get_target_device_info(mpt, page_address,
6302                             &devhdl, &ptgt);
6303                         if (rval == DEV_INFO_WRONG_DEVICE_TYPE) {
6304                                 mptsas_log(mpt, CE_NOTE,
6305                                     "mptsas_handle_topo_change: target %d is "
6306                                     "not a SAS/SATA device. \n",
6307                                     topo_node->devhdl);
6308                         } else if (rval == DEV_INFO_FAIL_ALLOC) {
6309                                 mptsas_log(mpt, CE_NOTE,
6310                                     "mptsas_handle_topo_change: could not "
6311                                     "allocate memory. \n");
6312                         }
6313                         /*
6314                          * If rval is DEV_INFO_PHYS_DISK than there is nothing
6315                          * else to do, just leave.
6316                          */
6317                         if (rval != DEV_INFO_SUCCESS) {
6318                                 return;
6319                         }
6320                 }
6321 
6322                 ASSERT(ptgt->m_devhdl == topo_node->devhdl);
6323 
6324                 mutex_exit(&mpt->m_mutex);
6325                 flags = topo_node->flags;
6326 
6327                 if (flags == MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED) {
6328                         phymask = ptgt->m_addr.mta_phymask;
6329                         phy_mask_name = kmem_zalloc(MPTSAS_MAX_PHYS, KM_SLEEP);
6330                         (void) sprintf(phy_mask_name, "%x", phymask);
6331                         parent = scsi_hba_iport_find(mpt->m_dip,
6332                             phy_mask_name);
6333                         kmem_free(phy_mask_name, MPTSAS_MAX_PHYS);
6334                         if (parent == NULL) {
6335                                 mptsas_log(mpt, CE_WARN, "Failed to find a "
6336                                     "iport for PD, should not happen!");
6337                                 mutex_enter(&mpt->m_mutex);
6338                                 break;
6339                         }
6340                 }
6341 
6342                 if (flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) {
6343                         ndi_devi_enter(parent, &circ1);
6344                         (void) mptsas_config_raid(parent, topo_node->devhdl,
6345                             &lundip);
6346                         ndi_devi_exit(parent, circ1);
6347                 } else {
6348                         /*
6349                          * hold nexus for bus configure
6350                          */
6351                         ndi_devi_enter(scsi_vhci_dip, &circ);
6352                         ndi_devi_enter(parent, &circ1);
6353                         rval = mptsas_config_target(parent, ptgt);
6354                         /*
6355                          * release nexus for bus configure
6356                          */
6357                         ndi_devi_exit(parent, circ1);
6358                         ndi_devi_exit(scsi_vhci_dip, circ);
6359 
6360                         /*
6361                          * Add parent's props for SMHBA support
6362                          */
6363                         if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6364                                 bzero(attached_wwnstr,
6365                                     sizeof (attached_wwnstr));
6366                                 (void) sprintf(attached_wwnstr, "w%016"PRIx64,
6367                                     ptgt->m_addr.mta_wwn);
6368                                 if (ddi_prop_update_string(DDI_DEV_T_NONE,
6369                                     parent,
6370                                     SCSI_ADDR_PROP_ATTACHED_PORT,
6371                                     attached_wwnstr)
6372                                     != DDI_PROP_SUCCESS) {
6373                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6374                                             parent,
6375                                             SCSI_ADDR_PROP_ATTACHED_PORT);
6376                                         mptsas_log(mpt, CE_WARN, "Failed to"
6377                                             "attached-port props");
6378                                         return;
6379                                 }
6380                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6381                                     MPTSAS_NUM_PHYS, 1) !=
6382                                     DDI_PROP_SUCCESS) {
6383                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6384                                             parent, MPTSAS_NUM_PHYS);
6385                                         mptsas_log(mpt, CE_WARN, "Failed to"
6386                                             " create num-phys props");
6387                                         return;
6388                                 }
6389 
6390                                 /*
6391                                  * Update PHY info for smhba
6392                                  */
6393                                 mutex_enter(&mpt->m_mutex);
6394                                 if (mptsas_smhba_phy_init(mpt)) {
6395                                         mutex_exit(&mpt->m_mutex);
6396                                         mptsas_log(mpt, CE_WARN, "mptsas phy"
6397                                             " update failed");
6398                                         return;
6399                                 }
6400                                 mutex_exit(&mpt->m_mutex);
6401 
6402                                 /*
6403                                  * topo_node->un.physport is really the PHY#
6404                                  * for direct attached devices
6405                                  */
6406                                 mptsas_smhba_set_one_phy_props(mpt, parent,
6407                                     topo_node->un.physport, &attached_devhdl);
6408 
6409                                 if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6410                                     MPTSAS_VIRTUAL_PORT, 0) !=
6411                                     DDI_PROP_SUCCESS) {
6412                                         (void) ddi_prop_remove(DDI_DEV_T_NONE,
6413                                             parent, MPTSAS_VIRTUAL_PORT);
6414                                         mptsas_log(mpt, CE_WARN,
6415                                             "mptsas virtual-port"
6416                                             "port prop update failed");
6417                                         return;
6418                                 }
6419                         }
6420                 }
6421                 mutex_enter(&mpt->m_mutex);
6422 
6423                 NDBG20(("mptsas%d handle_topo_change to online devhdl:%x, "
6424                     "phymask:%x.", mpt->m_instance, ptgt->m_devhdl,
6425                     ptgt->m_addr.mta_phymask));
6426                 break;
6427         }
6428         case MPTSAS_DR_EVENT_OFFLINE_TARGET:
6429         {
6430                 devhdl = topo_node->devhdl;
6431                 ptgt = refhash_linear_search(mpt->m_targets,
6432                     mptsas_target_eval_devhdl, &devhdl);
6433                 if (ptgt == NULL)
6434                         break;
6435 
6436                 sas_wwn = ptgt->m_addr.mta_wwn;
6437                 phy = ptgt->m_phynum;
6438 
6439                 addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
6440 
6441                 if (sas_wwn) {
6442                         (void) sprintf(addr, "w%016"PRIx64, sas_wwn);
6443                 } else {
6444                         (void) sprintf(addr, "p%x", phy);
6445                 }
6446                 ASSERT(ptgt->m_devhdl == devhdl);
6447 
6448                 if ((topo_node->flags == MPTSAS_TOPO_FLAG_RAID_ASSOCIATED) ||
6449                     (topo_node->flags ==
6450                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED)) {
6451                         /*
6452                          * Get latest RAID info if RAID volume status changes
6453                          * or Phys Disk status changes
6454                          */
6455                         (void) mptsas_get_raid_info(mpt);
6456                 }
6457                 /*
6458                  * Abort all outstanding command on the device
6459                  */
6460                 rval = mptsas_do_scsi_reset(mpt, devhdl);
6461                 if (rval) {
6462                         NDBG20(("mptsas%d handle_topo_change to reset target "
6463                             "before offline devhdl:%x, phymask:%x, rval:%x",
6464                             mpt->m_instance, ptgt->m_devhdl,
6465                             ptgt->m_addr.mta_phymask, rval));
6466                 }
6467 
6468                 mutex_exit(&mpt->m_mutex);
6469 
6470                 ndi_devi_enter(scsi_vhci_dip, &circ);
6471                 ndi_devi_enter(parent, &circ1);
6472                 rval = mptsas_offline_target(parent, addr);
6473                 ndi_devi_exit(parent, circ1);
6474                 ndi_devi_exit(scsi_vhci_dip, circ);
6475                 NDBG20(("mptsas%d handle_topo_change to offline devhdl:%x, "
6476                     "phymask:%x, rval:%x", mpt->m_instance,
6477                     ptgt->m_devhdl, ptgt->m_addr.mta_phymask, rval));
6478 
6479                 kmem_free(addr, SCSI_MAXNAMELEN);
6480 
6481                 /*
6482                  * Clear parent's props for SMHBA support
6483                  */
6484                 flags = topo_node->flags;
6485                 if (flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) {
6486                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6487                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6488                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6489                             DDI_PROP_SUCCESS) {
6490                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6491                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6492                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6493                                     "prop update failed");
6494                                 break;
6495                         }
6496                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6497                             MPTSAS_NUM_PHYS, 0) !=
6498                             DDI_PROP_SUCCESS) {
6499                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6500                                     MPTSAS_NUM_PHYS);
6501                                 mptsas_log(mpt, CE_WARN, "mptsas num phys "
6502                                     "prop update failed");
6503                                 break;
6504                         }
6505                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6506                             MPTSAS_VIRTUAL_PORT, 1) !=
6507                             DDI_PROP_SUCCESS) {
6508                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6509                                     MPTSAS_VIRTUAL_PORT);
6510                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6511                                     "prop update failed");
6512                                 break;
6513                         }
6514                 }
6515 
6516                 mutex_enter(&mpt->m_mutex);
6517                 ptgt->m_led_status = 0;
6518                 (void) mptsas_flush_led_status(mpt, ptgt);
6519                 if (rval == DDI_SUCCESS) {
6520                         refhash_remove(mpt->m_targets, ptgt);
6521                         ptgt = NULL;
6522                 } else {
6523                         /*
6524                          * clean DR_INTRANSITION flag to allow I/O down to
6525                          * PHCI driver since failover finished.
6526                          * Invalidate the devhdl
6527                          */
6528                         ptgt->m_devhdl = MPTSAS_INVALID_DEVHDL;
6529                         ptgt->m_tgt_unconfigured = 0;
6530                         mutex_enter(&mpt->m_tx_waitq_mutex);
6531                         ptgt->m_dr_flag = MPTSAS_DR_INACTIVE;
6532                         mutex_exit(&mpt->m_tx_waitq_mutex);
6533                 }
6534 
6535                 /*
6536                  * Send SAS IO Unit Control to free the dev handle
6537                  */
6538                 if ((flags == MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE) ||
6539                     (flags == MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE)) {
6540                         rval = mptsas_free_devhdl(mpt, devhdl);
6541 
6542                         NDBG20(("mptsas%d handle_topo_change to remove "
6543                             "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6544                             rval));
6545                 }
6546 
6547                 break;
6548         }
6549         case MPTSAS_TOPO_FLAG_REMOVE_HANDLE:
6550         {
6551                 devhdl = topo_node->devhdl;
6552                 /*
6553                  * If this is the remove handle event, do a reset first.
6554                  */
6555                 if (topo_node->event == MPTSAS_TOPO_FLAG_REMOVE_HANDLE) {
6556                         rval = mptsas_do_scsi_reset(mpt, devhdl);
6557                         if (rval) {
6558                                 NDBG20(("mpt%d reset target before remove "
6559                                     "devhdl:%x, rval:%x", mpt->m_instance,
6560                                     devhdl, rval));
6561                         }
6562                 }
6563 
6564                 /*
6565                  * Send SAS IO Unit Control to free the dev handle
6566                  */
6567                 rval = mptsas_free_devhdl(mpt, devhdl);
6568                 NDBG20(("mptsas%d handle_topo_change to remove "
6569                     "devhdl:%x, rval:%x", mpt->m_instance, devhdl,
6570                     rval));
6571                 break;
6572         }
6573         case MPTSAS_DR_EVENT_RECONFIG_SMP:
6574         {
6575                 mptsas_smp_t smp;
6576                 dev_info_t *smpdip;
6577 
6578                 devhdl = topo_node->devhdl;
6579 
6580                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
6581                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)devhdl;
6582                 rval = mptsas_get_sas_expander_page0(mpt, page_address, &smp);
6583                 if (rval != DDI_SUCCESS) {
6584                         mptsas_log(mpt, CE_WARN, "failed to online smp, "
6585                             "handle %x", devhdl);
6586                         return;
6587                 }
6588 
6589                 psmp = mptsas_smp_alloc(mpt, &smp);
6590                 if (psmp == NULL) {
6591                         return;
6592                 }
6593 
6594                 mutex_exit(&mpt->m_mutex);
6595                 ndi_devi_enter(parent, &circ1);
6596                 (void) mptsas_online_smp(parent, psmp, &smpdip);
6597                 ndi_devi_exit(parent, circ1);
6598 
6599                 mutex_enter(&mpt->m_mutex);
6600                 break;
6601         }
6602         case MPTSAS_DR_EVENT_OFFLINE_SMP:
6603         {
6604                 devhdl = topo_node->devhdl;
6605                 uint32_t dev_info;
6606 
6607                 psmp = refhash_linear_search(mpt->m_smp_targets,
6608                     mptsas_smp_eval_devhdl, &devhdl);
6609                 if (psmp == NULL)
6610                         break;
6611                 /*
6612                  * The mptsas_smp_t data is released only if the dip is offlined
6613                  * successfully.
6614                  */
6615                 mutex_exit(&mpt->m_mutex);
6616 
6617                 ndi_devi_enter(parent, &circ1);
6618                 rval = mptsas_offline_smp(parent, psmp, NDI_DEVI_REMOVE);
6619                 ndi_devi_exit(parent, circ1);
6620 
6621                 dev_info = psmp->m_deviceinfo;
6622                 if ((dev_info & DEVINFO_DIRECT_ATTACHED) ==
6623                     DEVINFO_DIRECT_ATTACHED) {
6624                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6625                             MPTSAS_VIRTUAL_PORT, 1) !=
6626                             DDI_PROP_SUCCESS) {
6627                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6628                                     MPTSAS_VIRTUAL_PORT);
6629                                 mptsas_log(mpt, CE_WARN, "mptsas virtual port "
6630                                     "prop update failed");
6631                                 return;
6632                         }
6633                         /*
6634                          * Check whether the smp connected to the iport,
6635                          */
6636                         if (ddi_prop_update_int(DDI_DEV_T_NONE, parent,
6637                             MPTSAS_NUM_PHYS, 0) !=
6638                             DDI_PROP_SUCCESS) {
6639                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6640                                     MPTSAS_NUM_PHYS);
6641                                 mptsas_log(mpt, CE_WARN, "mptsas num phys"
6642                                     "prop update failed");
6643                                 return;
6644                         }
6645                         /*
6646                          * Clear parent's attached-port props
6647                          */
6648                         bzero(attached_wwnstr, sizeof (attached_wwnstr));
6649                         if (ddi_prop_update_string(DDI_DEV_T_NONE, parent,
6650                             SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwnstr) !=
6651                             DDI_PROP_SUCCESS) {
6652                                 (void) ddi_prop_remove(DDI_DEV_T_NONE, parent,
6653                                     SCSI_ADDR_PROP_ATTACHED_PORT);
6654                                 mptsas_log(mpt, CE_WARN, "mptsas attached port "
6655                                     "prop update failed");
6656                                 return;
6657                         }
6658                 }
6659 
6660                 mutex_enter(&mpt->m_mutex);
6661                 NDBG20(("mptsas%d handle_topo_change to remove devhdl:%x, "
6662                     "rval:%x", mpt->m_instance, psmp->m_devhdl, rval));
6663                 if (rval == DDI_SUCCESS) {
6664                         refhash_remove(mpt->m_smp_targets, psmp);
6665                 } else {
6666                         psmp->m_devhdl = MPTSAS_INVALID_DEVHDL;
6667                 }
6668 
6669                 bzero(attached_wwnstr, sizeof (attached_wwnstr));
6670 
6671                 break;
6672         }
6673         default:
6674                 return;
6675         }
6676 }
6677 
6678 /*
6679  * Record the event if its type is enabled in mpt instance by ioctl.
6680  */
6681 static void
6682 mptsas_record_event(void *args)
6683 {
6684         m_replyh_arg_t                  *replyh_arg;
6685         pMpi2EventNotificationReply_t   eventreply;
6686         uint32_t                        event, rfm;
6687         mptsas_t                        *mpt;
6688         int                             i, j;
6689         uint16_t                        event_data_len;
6690         boolean_t                       sendAEN = FALSE;
6691 
6692         replyh_arg = (m_replyh_arg_t *)args;
6693         rfm = replyh_arg->rfm;
6694         mpt = replyh_arg->mpt;
6695 
6696         eventreply = (pMpi2EventNotificationReply_t)
6697             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6698         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6699 
6700 
6701         /*
6702          * Generate a system event to let anyone who cares know that a
6703          * LOG_ENTRY_ADDED event has occurred.  This is sent no matter what the
6704          * event mask is set to.
6705          */
6706         if (event == MPI2_EVENT_LOG_ENTRY_ADDED) {
6707                 sendAEN = TRUE;
6708         }
6709 
6710         /*
6711          * Record the event only if it is not masked.  Determine which dword
6712          * and bit of event mask to test.
6713          */
6714         i = (uint8_t)(event / 32);
6715         j = (uint8_t)(event % 32);
6716         if ((i < 4) && ((1 << j) & mpt->m_event_mask[i])) {
6717                 i = mpt->m_event_index;
6718                 mpt->m_events[i].Type = event;
6719                 mpt->m_events[i].Number = ++mpt->m_event_number;
6720                 bzero(mpt->m_events[i].Data, MPTSAS_MAX_EVENT_DATA_LENGTH * 4);
6721                 event_data_len = ddi_get16(mpt->m_acc_reply_frame_hdl,
6722                     &eventreply->EventDataLength);
6723 
6724                 if (event_data_len > 0) {
6725                         /*
6726                          * Limit data to size in m_event entry
6727                          */
6728                         if (event_data_len > MPTSAS_MAX_EVENT_DATA_LENGTH) {
6729                                 event_data_len = MPTSAS_MAX_EVENT_DATA_LENGTH;
6730                         }
6731                         for (j = 0; j < event_data_len; j++) {
6732                                 mpt->m_events[i].Data[j] =
6733                                     ddi_get32(mpt->m_acc_reply_frame_hdl,
6734                                     &(eventreply->EventData[j]));
6735                         }
6736 
6737                         /*
6738                          * check for index wrap-around
6739                          */
6740                         if (++i == MPTSAS_EVENT_QUEUE_SIZE) {
6741                                 i = 0;
6742                         }
6743                         mpt->m_event_index = (uint8_t)i;
6744 
6745                         /*
6746                          * Set flag to send the event.
6747                          */
6748                         sendAEN = TRUE;
6749                 }
6750         }
6751 
6752         /*
6753          * Generate a system event if flag is set to let anyone who cares know
6754          * that an event has occurred.
6755          */
6756         if (sendAEN) {
6757                 (void) ddi_log_sysevent(mpt->m_dip, DDI_VENDOR_LSI, "MPT_SAS",
6758                     "SAS", NULL, NULL, DDI_NOSLEEP);
6759         }
6760 }
6761 
6762 #define SMP_RESET_IN_PROGRESS MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS
6763 /*
6764  * handle sync events from ioc in interrupt
6765  * return value:
6766  * DDI_SUCCESS: The event is handled by this func
6767  * DDI_FAILURE: Event is not handled
6768  */
6769 static int
6770 mptsas_handle_event_sync(void *args)
6771 {
6772         m_replyh_arg_t                  *replyh_arg;
6773         pMpi2EventNotificationReply_t   eventreply;
6774         uint32_t                        event, rfm;
6775         mptsas_t                        *mpt;
6776         uint_t                          iocstatus;
6777 
6778         replyh_arg = (m_replyh_arg_t *)args;
6779         rfm = replyh_arg->rfm;
6780         mpt = replyh_arg->mpt;
6781 
6782         ASSERT(mutex_owned(&mpt->m_mutex));
6783 
6784         eventreply = (pMpi2EventNotificationReply_t)
6785             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
6786         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
6787 
6788         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
6789             &eventreply->IOCStatus)) {
6790                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
6791                         mptsas_log(mpt, CE_WARN,
6792                             "!mptsas_handle_event_sync: event 0x%x, "
6793                             "IOCStatus=0x%x, "
6794                             "IOCLogInfo=0x%x", event, iocstatus,
6795                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6796                             &eventreply->IOCLogInfo));
6797                 } else {
6798                         mptsas_log(mpt, CE_WARN,
6799                             "mptsas_handle_event_sync: event 0x%x, "
6800                             "IOCStatus=0x%x, "
6801                             "(IOCLogInfo=0x%x)", event, iocstatus,
6802                             ddi_get32(mpt->m_acc_reply_frame_hdl,
6803                             &eventreply->IOCLogInfo));
6804                 }
6805         }
6806 
6807         /*
6808          * figure out what kind of event we got and handle accordingly
6809          */
6810         switch (event) {
6811         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
6812         {
6813                 pMpi2EventDataSasTopologyChangeList_t   sas_topo_change_list;
6814                 uint8_t                         num_entries, expstatus, phy;
6815                 uint8_t                         phystatus, physport, state, i;
6816                 uint8_t                         start_phy_num, link_rate;
6817                 uint16_t                        dev_handle, reason_code;
6818                 uint16_t                        enc_handle, expd_handle;
6819                 char                            string[80], curr[80], prev[80];
6820                 mptsas_topo_change_list_t       *topo_head = NULL;
6821                 mptsas_topo_change_list_t       *topo_tail = NULL;
6822                 mptsas_topo_change_list_t       *topo_node = NULL;
6823                 mptsas_target_t                 *ptgt;
6824                 mptsas_smp_t                    *psmp;
6825                 uint8_t                         flags = 0, exp_flag;
6826                 smhba_info_t                    *pSmhba = NULL;
6827 
6828                 NDBG20(("mptsas_handle_event_sync: SAS topology change"));
6829 
6830                 sas_topo_change_list = (pMpi2EventDataSasTopologyChangeList_t)
6831                     eventreply->EventData;
6832 
6833                 enc_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6834                     &sas_topo_change_list->EnclosureHandle);
6835                 expd_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6836                     &sas_topo_change_list->ExpanderDevHandle);
6837                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
6838                     &sas_topo_change_list->NumEntries);
6839                 start_phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
6840                     &sas_topo_change_list->StartPhyNum);
6841                 expstatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6842                     &sas_topo_change_list->ExpStatus);
6843                 physport = ddi_get8(mpt->m_acc_reply_frame_hdl,
6844                     &sas_topo_change_list->PhysicalPort);
6845 
6846                 string[0] = 0;
6847                 if (expd_handle) {
6848                         flags = MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED;
6849                         switch (expstatus) {
6850                         case MPI2_EVENT_SAS_TOPO_ES_ADDED:
6851                                 (void) sprintf(string, " added");
6852                                 /*
6853                                  * New expander device added
6854                                  */
6855                                 mpt->m_port_chng = 1;
6856                                 topo_node = kmem_zalloc(
6857                                     sizeof (mptsas_topo_change_list_t),
6858                                     KM_SLEEP);
6859                                 topo_node->mpt = mpt;
6860                                 topo_node->event = MPTSAS_DR_EVENT_RECONFIG_SMP;
6861                                 topo_node->un.physport = physport;
6862                                 topo_node->devhdl = expd_handle;
6863                                 topo_node->flags = flags;
6864                                 topo_node->object = NULL;
6865                                 if (topo_head == NULL) {
6866                                         topo_head = topo_tail = topo_node;
6867                                 } else {
6868                                         topo_tail->next = topo_node;
6869                                         topo_tail = topo_node;
6870                                 }
6871                                 break;
6872                         case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
6873                                 (void) sprintf(string, " not responding, "
6874                                     "removed");
6875                                 psmp = refhash_linear_search(mpt->m_smp_targets,
6876                                     mptsas_smp_eval_devhdl, &expd_handle);
6877                                 if (psmp == NULL)
6878                                         break;
6879 
6880                                 topo_node = kmem_zalloc(
6881                                     sizeof (mptsas_topo_change_list_t),
6882                                     KM_SLEEP);
6883                                 topo_node->mpt = mpt;
6884                                 topo_node->un.phymask =
6885                                     psmp->m_addr.mta_phymask;
6886                                 topo_node->event = MPTSAS_DR_EVENT_OFFLINE_SMP;
6887                                 topo_node->devhdl = expd_handle;
6888                                 topo_node->flags = flags;
6889                                 topo_node->object = NULL;
6890                                 if (topo_head == NULL) {
6891                                         topo_head = topo_tail = topo_node;
6892                                 } else {
6893                                         topo_tail->next = topo_node;
6894                                         topo_tail = topo_node;
6895                                 }
6896                                 break;
6897                         case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
6898                                 break;
6899                         case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
6900                                 (void) sprintf(string, " not responding, "
6901                                     "delaying removal");
6902                                 break;
6903                         default:
6904                                 break;
6905                         }
6906                 } else {
6907                         flags = MPTSAS_TOPO_FLAG_DIRECT_ATTACHED_DEVICE;
6908                 }
6909 
6910                 NDBG20(("SAS TOPOLOGY CHANGE for enclosure %x expander %x%s\n",
6911                     enc_handle, expd_handle, string));
6912                 for (i = 0; i < num_entries; i++) {
6913                         phy = i + start_phy_num;
6914                         phystatus = ddi_get8(mpt->m_acc_reply_frame_hdl,
6915                             &sas_topo_change_list->PHY[i].PhyStatus);
6916                         dev_handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
6917                             &sas_topo_change_list->PHY[i].AttachedDevHandle);
6918                         reason_code = phystatus & MPI2_EVENT_SAS_TOPO_RC_MASK;
6919                         /*
6920                          * Filter out processing of Phy Vacant Status unless
6921                          * the reason code is "Not Responding".  Process all
6922                          * other combinations of Phy Status and Reason Codes.
6923                          */
6924                         if ((phystatus &
6925                             MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) &&
6926                             (reason_code !=
6927                             MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) {
6928                                 continue;
6929                         }
6930                         curr[0] = 0;
6931                         prev[0] = 0;
6932                         string[0] = 0;
6933                         switch (reason_code) {
6934                         case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
6935                         {
6936                                 NDBG20(("mptsas%d phy %d physical_port %d "
6937                                     "dev_handle %d added", mpt->m_instance, phy,
6938                                     physport, dev_handle));
6939                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
6940                                     &sas_topo_change_list->PHY[i].LinkRate);
6941                                 state = (link_rate &
6942                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
6943                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
6944                                 switch (state) {
6945                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
6946                                         (void) sprintf(curr, "is disabled");
6947                                         break;
6948                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
6949                                         (void) sprintf(curr, "is offline, "
6950                                             "failed speed negotiation");
6951                                         break;
6952                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
6953                                         (void) sprintf(curr, "SATA OOB "
6954                                             "complete");
6955                                         break;
6956                                 case SMP_RESET_IN_PROGRESS:
6957                                         (void) sprintf(curr, "SMP reset in "
6958                                             "progress");
6959                                         break;
6960                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
6961                                         (void) sprintf(curr, "is online at "
6962                                             "1.5 Gbps");
6963                                         break;
6964                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
6965                                         (void) sprintf(curr, "is online at 3.0 "
6966                                             "Gbps");
6967                                         break;
6968                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
6969                                         (void) sprintf(curr, "is online at 6.0 "
6970                                             "Gbps");
6971                                         break;
6972                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
6973                                         (void) sprintf(curr,
6974                                             "is online at 12.0 Gbps");
6975                                         break;
6976                                 default:
6977                                         (void) sprintf(curr, "state is "
6978                                             "unknown");
6979                                         break;
6980                                 }
6981                                 /*
6982                                  * New target device added into the system.
6983                                  * Set association flag according to if an
6984                                  * expander is used or not.
6985                                  */
6986                                 exp_flag =
6987                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
6988                                 if (flags ==
6989                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
6990                                         flags = exp_flag;
6991                                 }
6992                                 topo_node = kmem_zalloc(
6993                                     sizeof (mptsas_topo_change_list_t),
6994                                     KM_SLEEP);
6995                                 topo_node->mpt = mpt;
6996                                 topo_node->event =
6997                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
6998                                 if (expd_handle == 0) {
6999                                         /*
7000                                          * Per MPI 2, if expander dev handle
7001                                          * is 0, it's a directly attached
7002                                          * device. So driver use PHY to decide
7003                                          * which iport is associated
7004                                          */
7005                                         physport = phy;
7006                                         mpt->m_port_chng = 1;
7007                                 }
7008                                 topo_node->un.physport = physport;
7009                                 topo_node->devhdl = dev_handle;
7010                                 topo_node->flags = flags;
7011                                 topo_node->object = NULL;
7012                                 if (topo_head == NULL) {
7013                                         topo_head = topo_tail = topo_node;
7014                                 } else {
7015                                         topo_tail->next = topo_node;
7016                                         topo_tail = topo_node;
7017                                 }
7018                                 break;
7019                         }
7020                         case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
7021                         {
7022                                 NDBG20(("mptsas%d phy %d physical_port %d "
7023                                     "dev_handle %d removed", mpt->m_instance,
7024                                     phy, physport, dev_handle));
7025                                 /*
7026                                  * Set association flag according to if an
7027                                  * expander is used or not.
7028                                  */
7029                                 exp_flag =
7030                                     MPTSAS_TOPO_FLAG_EXPANDER_ATTACHED_DEVICE;
7031                                 if (flags ==
7032                                     MPTSAS_TOPO_FLAG_EXPANDER_ASSOCIATED) {
7033                                         flags = exp_flag;
7034                                 }
7035                                 /*
7036                                  * Target device is removed from the system
7037                                  * Before the device is really offline from
7038                                  * from system.
7039                                  */
7040                                 ptgt = refhash_linear_search(mpt->m_targets,
7041                                     mptsas_target_eval_devhdl, &dev_handle);
7042                                 /*
7043                                  * If ptgt is NULL here, it means that the
7044                                  * DevHandle is not in the hash table.  This is
7045                                  * reasonable sometimes.  For example, if a
7046                                  * disk was pulled, then added, then pulled
7047                                  * again, the disk will not have been put into
7048                                  * the hash table because the add event will
7049                                  * have an invalid phymask.  BUT, this does not
7050                                  * mean that the DevHandle is invalid.  The
7051                                  * controller will still have a valid DevHandle
7052                                  * that must be removed.  To do this, use the
7053                                  * MPTSAS_TOPO_FLAG_REMOVE_HANDLE event.
7054                                  */
7055                                 if (ptgt == NULL) {
7056                                         topo_node = kmem_zalloc(
7057                                             sizeof (mptsas_topo_change_list_t),
7058                                             KM_SLEEP);
7059                                         topo_node->mpt = mpt;
7060                                         topo_node->un.phymask = 0;
7061                                         topo_node->event =
7062                                             MPTSAS_TOPO_FLAG_REMOVE_HANDLE;
7063                                         topo_node->devhdl = dev_handle;
7064                                         topo_node->flags = flags;
7065                                         topo_node->object = NULL;
7066                                         if (topo_head == NULL) {
7067                                                 topo_head = topo_tail =
7068                                                     topo_node;
7069                                         } else {
7070                                                 topo_tail->next = topo_node;
7071                                                 topo_tail = topo_node;
7072                                         }
7073                                         break;
7074                                 }
7075 
7076                                 /*
7077                                  * Update DR flag immediately avoid I/O failure
7078                                  * before failover finish. Pay attention to the
7079                                  * mutex protect, we need grab m_tx_waitq_mutex
7080                                  * during set m_dr_flag because we won't add
7081                                  * the following command into waitq, instead,
7082                                  * we need return TRAN_BUSY in the tran_start
7083                                  * context.
7084                                  */
7085                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7086                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7087                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7088 
7089                                 topo_node = kmem_zalloc(
7090                                     sizeof (mptsas_topo_change_list_t),
7091                                     KM_SLEEP);
7092                                 topo_node->mpt = mpt;
7093                                 topo_node->un.phymask =
7094                                     ptgt->m_addr.mta_phymask;
7095                                 topo_node->event =
7096                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7097                                 topo_node->devhdl = dev_handle;
7098                                 topo_node->flags = flags;
7099                                 topo_node->object = NULL;
7100                                 if (topo_head == NULL) {
7101                                         topo_head = topo_tail = topo_node;
7102                                 } else {
7103                                         topo_tail->next = topo_node;
7104                                         topo_tail = topo_node;
7105                                 }
7106                                 break;
7107                         }
7108                         case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
7109                                 link_rate = ddi_get8(mpt->m_acc_reply_frame_hdl,
7110                                     &sas_topo_change_list->PHY[i].LinkRate);
7111                                 state = (link_rate &
7112                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK) >>
7113                                     MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT;
7114                                 pSmhba = &mpt->m_phy_info[i].smhba_info;
7115                                 pSmhba->negotiated_link_rate = state;
7116                                 switch (state) {
7117                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7118                                         (void) sprintf(curr, "is disabled");
7119                                         mptsas_smhba_log_sysevent(mpt,
7120                                             ESC_SAS_PHY_EVENT,
7121                                             SAS_PHY_REMOVE,
7122                                             &mpt->m_phy_info[i].smhba_info);
7123                                         mpt->m_phy_info[i].smhba_info.
7124                                             negotiated_link_rate
7125                                             = 0x1;
7126                                         break;
7127                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7128                                         (void) sprintf(curr, "is offline, "
7129                                             "failed speed negotiation");
7130                                         mptsas_smhba_log_sysevent(mpt,
7131                                             ESC_SAS_PHY_EVENT,
7132                                             SAS_PHY_OFFLINE,
7133                                             &mpt->m_phy_info[i].smhba_info);
7134                                         break;
7135                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7136                                         (void) sprintf(curr, "SATA OOB "
7137                                             "complete");
7138                                         break;
7139                                 case SMP_RESET_IN_PROGRESS:
7140                                         (void) sprintf(curr, "SMP reset in "
7141                                             "progress");
7142                                         break;
7143                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7144                                         (void) sprintf(curr, "is online at "
7145                                             "1.5 Gbps");
7146                                         if ((expd_handle == 0) &&
7147                                             (enc_handle == 1)) {
7148                                                 mpt->m_port_chng = 1;
7149                                         }
7150                                         mptsas_smhba_log_sysevent(mpt,
7151                                             ESC_SAS_PHY_EVENT,
7152                                             SAS_PHY_ONLINE,
7153                                             &mpt->m_phy_info[i].smhba_info);
7154                                         break;
7155                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7156                                         (void) sprintf(curr, "is online at 3.0 "
7157                                             "Gbps");
7158                                         if ((expd_handle == 0) &&
7159                                             (enc_handle == 1)) {
7160                                                 mpt->m_port_chng = 1;
7161                                         }
7162                                         mptsas_smhba_log_sysevent(mpt,
7163                                             ESC_SAS_PHY_EVENT,
7164                                             SAS_PHY_ONLINE,
7165                                             &mpt->m_phy_info[i].smhba_info);
7166                                         break;
7167                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7168                                         (void) sprintf(curr, "is online at "
7169                                             "6.0 Gbps");
7170                                         if ((expd_handle == 0) &&
7171                                             (enc_handle == 1)) {
7172                                                 mpt->m_port_chng = 1;
7173                                         }
7174                                         mptsas_smhba_log_sysevent(mpt,
7175                                             ESC_SAS_PHY_EVENT,
7176                                             SAS_PHY_ONLINE,
7177                                             &mpt->m_phy_info[i].smhba_info);
7178                                         break;
7179                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7180                                         (void) sprintf(curr, "is online at "
7181                                             "12.0 Gbps");
7182                                         if ((expd_handle == 0) &&
7183                                             (enc_handle == 1)) {
7184                                                 mpt->m_port_chng = 1;
7185                                         }
7186                                         mptsas_smhba_log_sysevent(mpt,
7187                                             ESC_SAS_PHY_EVENT,
7188                                             SAS_PHY_ONLINE,
7189                                             &mpt->m_phy_info[i].smhba_info);
7190                                         break;
7191                                 default:
7192                                         (void) sprintf(curr, "state is "
7193                                             "unknown");
7194                                         break;
7195                                 }
7196 
7197                                 state = (link_rate &
7198                                     MPI2_EVENT_SAS_TOPO_LR_PREV_MASK) >>
7199                                     MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT;
7200                                 switch (state) {
7201                                 case MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED:
7202                                         (void) sprintf(prev, ", was disabled");
7203                                         break;
7204                                 case MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED:
7205                                         (void) sprintf(prev, ", was offline, "
7206                                             "failed speed negotiation");
7207                                         break;
7208                                 case MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE:
7209                                         (void) sprintf(prev, ", was SATA OOB "
7210                                             "complete");
7211                                         break;
7212                                 case SMP_RESET_IN_PROGRESS:
7213                                         (void) sprintf(prev, ", was SMP reset "
7214                                             "in progress");
7215                                         break;
7216                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_1_5:
7217                                         (void) sprintf(prev, ", was online at "
7218                                             "1.5 Gbps");
7219                                         break;
7220                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_3_0:
7221                                         (void) sprintf(prev, ", was online at "
7222                                             "3.0 Gbps");
7223                                         break;
7224                                 case MPI2_EVENT_SAS_TOPO_LR_RATE_6_0:
7225                                         (void) sprintf(prev, ", was online at "
7226                                             "6.0 Gbps");
7227                                         break;
7228                                 case MPI25_EVENT_SAS_TOPO_LR_RATE_12_0:
7229                                         (void) sprintf(prev, ", was online at "
7230                                             "12.0 Gbps");
7231                                         break;
7232                                 default:
7233                                 break;
7234                                 }
7235                                 (void) sprintf(&string[strlen(string)], "link "
7236                                     "changed, ");
7237                                 break;
7238                         case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
7239                                 continue;
7240                         case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
7241                                 (void) sprintf(&string[strlen(string)],
7242                                     "target not responding, delaying "
7243                                     "removal");
7244                                 break;
7245                         }
7246                         NDBG20(("mptsas%d phy %d DevHandle %x, %s%s%s\n",
7247                             mpt->m_instance, phy, dev_handle, string, curr,
7248                             prev));
7249                 }
7250                 if (topo_head != NULL) {
7251                         /*
7252                          * Launch DR taskq to handle topology change
7253                          */
7254                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7255                             mptsas_handle_dr, (void *)topo_head,
7256                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7257                                 while (topo_head != NULL) {
7258                                         topo_node = topo_head;
7259                                         topo_head = topo_head->next;
7260                                         kmem_free(topo_node,
7261                                             sizeof (mptsas_topo_change_list_t));
7262                                 }
7263                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7264                                     "for handle SAS DR event failed. \n");
7265                         }
7266                 }
7267                 break;
7268         }
7269         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7270         {
7271                 Mpi2EventDataIrConfigChangeList_t       *irChangeList;
7272                 mptsas_topo_change_list_t               *topo_head = NULL;
7273                 mptsas_topo_change_list_t               *topo_tail = NULL;
7274                 mptsas_topo_change_list_t               *topo_node = NULL;
7275                 mptsas_target_t                         *ptgt;
7276                 uint8_t                                 num_entries, i, reason;
7277                 uint16_t                                volhandle, diskhandle;
7278 
7279                 irChangeList = (pMpi2EventDataIrConfigChangeList_t)
7280                     eventreply->EventData;
7281                 num_entries = ddi_get8(mpt->m_acc_reply_frame_hdl,
7282                     &irChangeList->NumElements);
7283 
7284                 NDBG20(("mptsas%d IR_CONFIGURATION_CHANGE_LIST event received",
7285                     mpt->m_instance));
7286 
7287                 for (i = 0; i < num_entries; i++) {
7288                         reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7289                             &irChangeList->ConfigElement[i].ReasonCode);
7290                         volhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7291                             &irChangeList->ConfigElement[i].VolDevHandle);
7292                         diskhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7293                             &irChangeList->ConfigElement[i].PhysDiskDevHandle);
7294 
7295                         switch (reason) {
7296                         case MPI2_EVENT_IR_CHANGE_RC_ADDED:
7297                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
7298                         {
7299                                 NDBG20(("mptsas %d volume added\n",
7300                                     mpt->m_instance));
7301 
7302                                 topo_node = kmem_zalloc(
7303                                     sizeof (mptsas_topo_change_list_t),
7304                                     KM_SLEEP);
7305 
7306                                 topo_node->mpt = mpt;
7307                                 topo_node->event =
7308                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7309                                 topo_node->un.physport = 0xff;
7310                                 topo_node->devhdl = volhandle;
7311                                 topo_node->flags =
7312                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7313                                 topo_node->object = NULL;
7314                                 if (topo_head == NULL) {
7315                                         topo_head = topo_tail = topo_node;
7316                                 } else {
7317                                         topo_tail->next = topo_node;
7318                                         topo_tail = topo_node;
7319                                 }
7320                                 break;
7321                         }
7322                         case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
7323                         case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
7324                         {
7325                                 NDBG20(("mptsas %d volume deleted\n",
7326                                     mpt->m_instance));
7327                                 ptgt = refhash_linear_search(mpt->m_targets,
7328                                     mptsas_target_eval_devhdl, &volhandle);
7329                                 if (ptgt == NULL)
7330                                         break;
7331 
7332                                 /*
7333                                  * Clear any flags related to volume
7334                                  */
7335                                 (void) mptsas_delete_volume(mpt, volhandle);
7336 
7337                                 /*
7338                                  * Update DR flag immediately avoid I/O failure
7339                                  */
7340                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7341                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7342                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7343 
7344                                 topo_node = kmem_zalloc(
7345                                     sizeof (mptsas_topo_change_list_t),
7346                                     KM_SLEEP);
7347                                 topo_node->mpt = mpt;
7348                                 topo_node->un.phymask =
7349                                     ptgt->m_addr.mta_phymask;
7350                                 topo_node->event =
7351                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7352                                 topo_node->devhdl = volhandle;
7353                                 topo_node->flags =
7354                                     MPTSAS_TOPO_FLAG_RAID_ASSOCIATED;
7355                                 topo_node->object = (void *)ptgt;
7356                                 if (topo_head == NULL) {
7357                                         topo_head = topo_tail = topo_node;
7358                                 } else {
7359                                         topo_tail->next = topo_node;
7360                                         topo_tail = topo_node;
7361                                 }
7362                                 break;
7363                         }
7364                         case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
7365                         case MPI2_EVENT_IR_CHANGE_RC_HIDE:
7366                         {
7367                                 ptgt = refhash_linear_search(mpt->m_targets,
7368                                     mptsas_target_eval_devhdl, &diskhandle);
7369                                 if (ptgt == NULL)
7370                                         break;
7371 
7372                                 /*
7373                                  * Update DR flag immediately avoid I/O failure
7374                                  */
7375                                 mutex_enter(&mpt->m_tx_waitq_mutex);
7376                                 ptgt->m_dr_flag = MPTSAS_DR_INTRANSITION;
7377                                 mutex_exit(&mpt->m_tx_waitq_mutex);
7378 
7379                                 topo_node = kmem_zalloc(
7380                                     sizeof (mptsas_topo_change_list_t),
7381                                     KM_SLEEP);
7382                                 topo_node->mpt = mpt;
7383                                 topo_node->un.phymask =
7384                                     ptgt->m_addr.mta_phymask;
7385                                 topo_node->event =
7386                                     MPTSAS_DR_EVENT_OFFLINE_TARGET;
7387                                 topo_node->devhdl = diskhandle;
7388                                 topo_node->flags =
7389                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7390                                 topo_node->object = (void *)ptgt;
7391                                 if (topo_head == NULL) {
7392                                         topo_head = topo_tail = topo_node;
7393                                 } else {
7394                                         topo_tail->next = topo_node;
7395                                         topo_tail = topo_node;
7396                                 }
7397                                 break;
7398                         }
7399                         case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
7400                         case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
7401                         {
7402                                 /*
7403                                  * The physical drive is released by a IR
7404                                  * volume. But we cannot get the the physport
7405                                  * or phynum from the event data, so we only
7406                                  * can get the physport/phynum after SAS
7407                                  * Device Page0 request for the devhdl.
7408                                  */
7409                                 topo_node = kmem_zalloc(
7410                                     sizeof (mptsas_topo_change_list_t),
7411                                     KM_SLEEP);
7412                                 topo_node->mpt = mpt;
7413                                 topo_node->un.phymask = 0;
7414                                 topo_node->event =
7415                                     MPTSAS_DR_EVENT_RECONFIG_TARGET;
7416                                 topo_node->devhdl = diskhandle;
7417                                 topo_node->flags =
7418                                     MPTSAS_TOPO_FLAG_RAID_PHYSDRV_ASSOCIATED;
7419                                 topo_node->object = NULL;
7420                                 mpt->m_port_chng = 1;
7421                                 if (topo_head == NULL) {
7422                                         topo_head = topo_tail = topo_node;
7423                                 } else {
7424                                         topo_tail->next = topo_node;
7425                                         topo_tail = topo_node;
7426                                 }
7427                                 break;
7428                         }
7429                         default:
7430                                 break;
7431                         }
7432                 }
7433 
7434                 if (topo_head != NULL) {
7435                         /*
7436                          * Launch DR taskq to handle topology change
7437                          */
7438                         if ((ddi_taskq_dispatch(mpt->m_dr_taskq,
7439                             mptsas_handle_dr, (void *)topo_head,
7440                             DDI_NOSLEEP)) != DDI_SUCCESS) {
7441                                 while (topo_head != NULL) {
7442                                         topo_node = topo_head;
7443                                         topo_head = topo_head->next;
7444                                         kmem_free(topo_node,
7445                                             sizeof (mptsas_topo_change_list_t));
7446                                 }
7447                                 mptsas_log(mpt, CE_NOTE, "mptsas start taskq "
7448                                     "for handle SAS DR event failed. \n");
7449                         }
7450                 }
7451                 break;
7452         }
7453         default:
7454                 return (DDI_FAILURE);
7455         }
7456 
7457         return (DDI_SUCCESS);
7458 }
7459 
7460 /*
7461  * handle events from ioc
7462  */
7463 static void
7464 mptsas_handle_event(void *args)
7465 {
7466         m_replyh_arg_t                  *replyh_arg;
7467         pMpi2EventNotificationReply_t   eventreply;
7468         uint32_t                        event, iocloginfo, rfm;
7469         uint32_t                        status;
7470         uint8_t                         port;
7471         mptsas_t                        *mpt;
7472         uint_t                          iocstatus;
7473 
7474         replyh_arg = (m_replyh_arg_t *)args;
7475         rfm = replyh_arg->rfm;
7476         mpt = replyh_arg->mpt;
7477 
7478         mutex_enter(&mpt->m_mutex);
7479         /*
7480          * If HBA is being reset, drop incoming event.
7481          */
7482         if (mpt->m_in_reset) {
7483                 NDBG20(("dropping event received prior to reset"));
7484                 mutex_exit(&mpt->m_mutex);
7485                 return;
7486         }
7487 
7488         eventreply = (pMpi2EventNotificationReply_t)
7489             (mpt->m_reply_frame + (rfm - mpt->m_reply_frame_dma_addr));
7490         event = ddi_get16(mpt->m_acc_reply_frame_hdl, &eventreply->Event);
7491 
7492         if (iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
7493             &eventreply->IOCStatus)) {
7494                 if (iocstatus == MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
7495                         mptsas_log(mpt, CE_WARN,
7496                             "!mptsas_handle_event: IOCStatus=0x%x, "
7497                             "IOCLogInfo=0x%x", iocstatus,
7498                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7499                             &eventreply->IOCLogInfo));
7500                 } else {
7501                         mptsas_log(mpt, CE_WARN,
7502                             "mptsas_handle_event: IOCStatus=0x%x, "
7503                             "IOCLogInfo=0x%x", iocstatus,
7504                             ddi_get32(mpt->m_acc_reply_frame_hdl,
7505                             &eventreply->IOCLogInfo));
7506                 }
7507         }
7508 
7509         /*
7510          * figure out what kind of event we got and handle accordingly
7511          */
7512         switch (event) {
7513         case MPI2_EVENT_LOG_ENTRY_ADDED:
7514                 break;
7515         case MPI2_EVENT_LOG_DATA:
7516                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7517                     &eventreply->IOCLogInfo);
7518                 NDBG20(("mptsas %d log info %x received.\n", mpt->m_instance,
7519                     iocloginfo));
7520                 break;
7521         case MPI2_EVENT_STATE_CHANGE:
7522                 NDBG20(("mptsas%d state change.", mpt->m_instance));
7523                 break;
7524         case MPI2_EVENT_HARD_RESET_RECEIVED:
7525                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7526                 break;
7527         case MPI2_EVENT_SAS_DISCOVERY:
7528         {
7529                 MPI2_EVENT_DATA_SAS_DISCOVERY   *sasdiscovery;
7530                 char                            string[80];
7531                 uint8_t                         rc;
7532 
7533                 sasdiscovery =
7534                     (pMpi2EventDataSasDiscovery_t)eventreply->EventData;
7535 
7536                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7537                     &sasdiscovery->ReasonCode);
7538                 port = ddi_get8(mpt->m_acc_reply_frame_hdl,
7539                     &sasdiscovery->PhysicalPort);
7540                 status = ddi_get32(mpt->m_acc_reply_frame_hdl,
7541                     &sasdiscovery->DiscoveryStatus);
7542 
7543                 string[0] = 0;
7544                 switch (rc) {
7545                 case MPI2_EVENT_SAS_DISC_RC_STARTED:
7546                         (void) sprintf(string, "STARTING");
7547                         break;
7548                 case MPI2_EVENT_SAS_DISC_RC_COMPLETED:
7549                         (void) sprintf(string, "COMPLETED");
7550                         break;
7551                 default:
7552                         (void) sprintf(string, "UNKNOWN");
7553                         break;
7554                 }
7555 
7556                 NDBG20(("SAS DISCOVERY is %s for port %d, status %x", string,
7557                     port, status));
7558 
7559                 break;
7560         }
7561         case MPI2_EVENT_EVENT_CHANGE:
7562                 NDBG20(("mptsas%d event change.", mpt->m_instance));
7563                 break;
7564         case MPI2_EVENT_TASK_SET_FULL:
7565         {
7566                 pMpi2EventDataTaskSetFull_t     taskfull;
7567 
7568                 taskfull = (pMpi2EventDataTaskSetFull_t)eventreply->EventData;
7569 
7570                 NDBG20(("TASK_SET_FULL received for mptsas%d, depth %d\n",
7571                     mpt->m_instance,  ddi_get16(mpt->m_acc_reply_frame_hdl,
7572                     &taskfull->CurrentDepth)));
7573                 break;
7574         }
7575         case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7576         {
7577                 /*
7578                  * SAS TOPOLOGY CHANGE LIST Event has already been handled
7579                  * in mptsas_handle_event_sync() of interrupt context
7580                  */
7581                 break;
7582         }
7583         case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7584         {
7585                 pMpi2EventDataSasEnclDevStatusChange_t  encstatus;
7586                 uint8_t                                 rc;
7587                 char                                    string[80];
7588 
7589                 encstatus = (pMpi2EventDataSasEnclDevStatusChange_t)
7590                     eventreply->EventData;
7591 
7592                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7593                     &encstatus->ReasonCode);
7594                 switch (rc) {
7595                 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
7596                         (void) sprintf(string, "added");
7597                         break;
7598                 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
7599                         (void) sprintf(string, ", not responding");
7600                         break;
7601                 default:
7602                 break;
7603                 }
7604                 NDBG20(("mptsas%d ENCLOSURE STATUS CHANGE for enclosure "
7605                     "%x%s\n", mpt->m_instance,
7606                     ddi_get16(mpt->m_acc_reply_frame_hdl,
7607                     &encstatus->EnclosureHandle), string));
7608                 break;
7609         }
7610 
7611         /*
7612          * MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE is handled by
7613          * mptsas_handle_event_sync,in here just send ack message.
7614          */
7615         case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7616         {
7617                 pMpi2EventDataSasDeviceStatusChange_t   statuschange;
7618                 uint8_t                                 rc;
7619                 uint16_t                                devhdl;
7620                 uint64_t                                wwn = 0;
7621                 uint32_t                                wwn_lo, wwn_hi;
7622 
7623                 statuschange = (pMpi2EventDataSasDeviceStatusChange_t)
7624                     eventreply->EventData;
7625                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7626                     &statuschange->ReasonCode);
7627                 wwn_lo = ddi_get32(mpt->m_acc_reply_frame_hdl,
7628                     (uint32_t *)(void *)&statuschange->SASAddress);
7629                 wwn_hi = ddi_get32(mpt->m_acc_reply_frame_hdl,
7630                     (uint32_t *)(void *)&statuschange->SASAddress + 1);
7631                 wwn = ((uint64_t)wwn_hi << 32) | wwn_lo;
7632                 devhdl =  ddi_get16(mpt->m_acc_reply_frame_hdl,
7633                     &statuschange->DevHandle);
7634 
7635                 NDBG13(("MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE wwn is %"PRIx64,
7636                     wwn));
7637 
7638                 switch (rc) {
7639                 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
7640                         NDBG20(("SMART data received, ASC/ASCQ = %02x/%02x",
7641                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7642                             &statuschange->ASC),
7643                             ddi_get8(mpt->m_acc_reply_frame_hdl,
7644                             &statuschange->ASCQ)));
7645                         break;
7646 
7647                 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
7648                         NDBG20(("Device not supported"));
7649                         break;
7650 
7651                 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
7652                         NDBG20(("IOC internally generated the Target Reset "
7653                             "for devhdl:%x", devhdl));
7654                         break;
7655 
7656                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
7657                         NDBG20(("IOC's internally generated Target Reset "
7658                             "completed for devhdl:%x", devhdl));
7659                         break;
7660 
7661                 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
7662                         NDBG20(("IOC internally generated Abort Task"));
7663                         break;
7664 
7665                 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
7666                         NDBG20(("IOC's internally generated Abort Task "
7667                             "completed"));
7668                         break;
7669 
7670                 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
7671                         NDBG20(("IOC internally generated Abort Task Set"));
7672                         break;
7673 
7674                 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
7675                         NDBG20(("IOC internally generated Clear Task Set"));
7676                         break;
7677 
7678                 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
7679                         NDBG20(("IOC internally generated Query Task"));
7680                         break;
7681 
7682                 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
7683                         NDBG20(("Device sent an Asynchronous Notification"));
7684                         break;
7685 
7686                 default:
7687                         break;
7688                 }
7689                 break;
7690         }
7691         case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7692         {
7693                 /*
7694                  * IR TOPOLOGY CHANGE LIST Event has already been handled
7695                  * in mpt_handle_event_sync() of interrupt context
7696                  */
7697                 break;
7698         }
7699         case MPI2_EVENT_IR_OPERATION_STATUS:
7700         {
7701                 Mpi2EventDataIrOperationStatus_t        *irOpStatus;
7702                 char                                    reason_str[80];
7703                 uint8_t                                 rc, percent;
7704                 uint16_t                                handle;
7705 
7706                 irOpStatus = (pMpi2EventDataIrOperationStatus_t)
7707                     eventreply->EventData;
7708                 rc = ddi_get8(mpt->m_acc_reply_frame_hdl,
7709                     &irOpStatus->RAIDOperation);
7710                 percent = ddi_get8(mpt->m_acc_reply_frame_hdl,
7711                     &irOpStatus->PercentComplete);
7712                 handle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7713                     &irOpStatus->VolDevHandle);
7714 
7715                 switch (rc) {
7716                         case MPI2_EVENT_IR_RAIDOP_RESYNC:
7717                                 (void) sprintf(reason_str, "resync");
7718                                 break;
7719                         case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
7720                                 (void) sprintf(reason_str, "online capacity "
7721                                     "expansion");
7722                                 break;
7723                         case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
7724                                 (void) sprintf(reason_str, "consistency check");
7725                                 break;
7726                         default:
7727                                 (void) sprintf(reason_str, "unknown reason %x",
7728                                     rc);
7729                 }
7730 
7731                 NDBG20(("mptsas%d raid operational status: (%s)"
7732                     "\thandle(0x%04x), percent complete(%d)\n",
7733                     mpt->m_instance, reason_str, handle, percent));
7734                 break;
7735         }
7736         case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7737         {
7738                 pMpi2EventDataSasBroadcastPrimitive_t   sas_broadcast;
7739                 uint8_t                                 phy_num;
7740                 uint8_t                                 primitive;
7741 
7742                 sas_broadcast = (pMpi2EventDataSasBroadcastPrimitive_t)
7743                     eventreply->EventData;
7744 
7745                 phy_num = ddi_get8(mpt->m_acc_reply_frame_hdl,
7746                     &sas_broadcast->PhyNum);
7747                 primitive = ddi_get8(mpt->m_acc_reply_frame_hdl,
7748                     &sas_broadcast->Primitive);
7749 
7750                 switch (primitive) {
7751                 case MPI2_EVENT_PRIMITIVE_CHANGE:
7752                         mptsas_smhba_log_sysevent(mpt,
7753                             ESC_SAS_HBA_PORT_BROADCAST,
7754                             SAS_PORT_BROADCAST_CHANGE,
7755                             &mpt->m_phy_info[phy_num].smhba_info);
7756                         break;
7757                 case MPI2_EVENT_PRIMITIVE_SES:
7758                         mptsas_smhba_log_sysevent(mpt,
7759                             ESC_SAS_HBA_PORT_BROADCAST,
7760                             SAS_PORT_BROADCAST_SES,
7761                             &mpt->m_phy_info[phy_num].smhba_info);
7762                         break;
7763                 case MPI2_EVENT_PRIMITIVE_EXPANDER:
7764                         mptsas_smhba_log_sysevent(mpt,
7765                             ESC_SAS_HBA_PORT_BROADCAST,
7766                             SAS_PORT_BROADCAST_D01_4,
7767                             &mpt->m_phy_info[phy_num].smhba_info);
7768                         break;
7769                 case MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT:
7770                         mptsas_smhba_log_sysevent(mpt,
7771                             ESC_SAS_HBA_PORT_BROADCAST,
7772                             SAS_PORT_BROADCAST_D04_7,
7773                             &mpt->m_phy_info[phy_num].smhba_info);
7774                         break;
7775                 case MPI2_EVENT_PRIMITIVE_RESERVED3:
7776                         mptsas_smhba_log_sysevent(mpt,
7777                             ESC_SAS_HBA_PORT_BROADCAST,
7778                             SAS_PORT_BROADCAST_D16_7,
7779                             &mpt->m_phy_info[phy_num].smhba_info);
7780                         break;
7781                 case MPI2_EVENT_PRIMITIVE_RESERVED4:
7782                         mptsas_smhba_log_sysevent(mpt,
7783                             ESC_SAS_HBA_PORT_BROADCAST,
7784                             SAS_PORT_BROADCAST_D29_7,
7785                             &mpt->m_phy_info[phy_num].smhba_info);
7786                         break;
7787                 case MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED:
7788                         mptsas_smhba_log_sysevent(mpt,
7789                             ESC_SAS_HBA_PORT_BROADCAST,
7790                             SAS_PORT_BROADCAST_D24_0,
7791                             &mpt->m_phy_info[phy_num].smhba_info);
7792                         break;
7793                 case MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED:
7794                         mptsas_smhba_log_sysevent(mpt,
7795                             ESC_SAS_HBA_PORT_BROADCAST,
7796                             SAS_PORT_BROADCAST_D27_4,
7797                             &mpt->m_phy_info[phy_num].smhba_info);
7798                         break;
7799                 default:
7800                         NDBG16(("mptsas%d: unknown BROADCAST PRIMITIVE"
7801                             " %x received",
7802                             mpt->m_instance, primitive));
7803                         break;
7804                 }
7805                 NDBG16(("mptsas%d sas broadcast primitive: "
7806                     "\tprimitive(0x%04x), phy(%d) complete\n",
7807                     mpt->m_instance, primitive, phy_num));
7808                 break;
7809         }
7810         case MPI2_EVENT_IR_VOLUME:
7811         {
7812                 Mpi2EventDataIrVolume_t         *irVolume;
7813                 uint16_t                        devhandle;
7814                 uint32_t                        state;
7815                 int                             config, vol;
7816                 uint8_t                         found = FALSE;
7817 
7818                 irVolume = (pMpi2EventDataIrVolume_t)eventreply->EventData;
7819                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7820                     &irVolume->NewValue);
7821                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7822                     &irVolume->VolDevHandle);
7823 
7824                 NDBG20(("EVENT_IR_VOLUME event is received"));
7825 
7826                 /*
7827                  * Get latest RAID info and then find the DevHandle for this
7828                  * event in the configuration.  If the DevHandle is not found
7829                  * just exit the event.
7830                  */
7831                 (void) mptsas_get_raid_info(mpt);
7832                 for (config = 0; (config < mpt->m_num_raid_configs) &&
7833                     (!found); config++) {
7834                         for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
7835                                 if (mpt->m_raidconfig[config].m_raidvol[vol].
7836                                     m_raidhandle == devhandle) {
7837                                         found = TRUE;
7838                                         break;
7839                                 }
7840                         }
7841                 }
7842                 if (!found) {
7843                         break;
7844                 }
7845 
7846                 switch (irVolume->ReasonCode) {
7847                 case MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED:
7848                 {
7849                         uint32_t i;
7850                         mpt->m_raidconfig[config].m_raidvol[vol].m_settings =
7851                             state;
7852 
7853                         i = state & MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING;
7854                         mptsas_log(mpt, CE_NOTE, " Volume %d settings changed"
7855                             ", auto-config of hot-swap drives is %s"
7856                             ", write caching is %s"
7857                             ", hot-spare pool mask is %02x\n",
7858                             vol, state &
7859                             MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE
7860                             ? "disabled" : "enabled",
7861                             i == MPI2_RAIDVOL0_SETTING_UNCHANGED
7862                             ? "controlled by member disks" :
7863                             i == MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING
7864                             ? "disabled" :
7865                             i == MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING
7866                             ? "enabled" :
7867                             "incorrectly set",
7868                             (state >> 16) & 0xff);
7869                                 break;
7870                 }
7871                 case MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED:
7872                 {
7873                         mpt->m_raidconfig[config].m_raidvol[vol].m_state =
7874                             (uint8_t)state;
7875 
7876                         mptsas_log(mpt, CE_NOTE,
7877                             "Volume %d is now %s\n", vol,
7878                             state == MPI2_RAID_VOL_STATE_OPTIMAL
7879                             ? "optimal" :
7880                             state == MPI2_RAID_VOL_STATE_DEGRADED
7881                             ? "degraded" :
7882                             state == MPI2_RAID_VOL_STATE_ONLINE
7883                             ? "online" :
7884                             state == MPI2_RAID_VOL_STATE_INITIALIZING
7885                             ? "initializing" :
7886                             state == MPI2_RAID_VOL_STATE_FAILED
7887                             ? "failed" :
7888                             state == MPI2_RAID_VOL_STATE_MISSING
7889                             ? "missing" :
7890                             "state unknown");
7891                         break;
7892                 }
7893                 case MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED:
7894                 {
7895                         mpt->m_raidconfig[config].m_raidvol[vol].
7896                             m_statusflags = state;
7897 
7898                         mptsas_log(mpt, CE_NOTE,
7899                             " Volume %d is now %s%s%s%s%s%s%s%s%s\n",
7900                             vol,
7901                             state & MPI2_RAIDVOL0_STATUS_FLAG_ENABLED
7902                             ? ", enabled" : ", disabled",
7903                             state & MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED
7904                             ? ", quiesced" : "",
7905                             state & MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE
7906                             ? ", inactive" : ", active",
7907                             state &
7908                             MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL
7909                             ? ", bad block table is full" : "",
7910                             state &
7911                             MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS
7912                             ? ", resync in progress" : "",
7913                             state & MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT
7914                             ? ", background initialization in progress" : "",
7915                             state &
7916                             MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION
7917                             ? ", capacity expansion in progress" : "",
7918                             state &
7919                             MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK
7920                             ? ", consistency check in progress" : "",
7921                             state & MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB
7922                             ? ", data scrub in progress" : "");
7923                         break;
7924                 }
7925                 default:
7926                         break;
7927                 }
7928                 break;
7929         }
7930         case MPI2_EVENT_IR_PHYSICAL_DISK:
7931         {
7932                 Mpi2EventDataIrPhysicalDisk_t   *irPhysDisk;
7933                 uint16_t                        devhandle, enchandle, slot;
7934                 uint32_t                        status, state;
7935                 uint8_t                         physdisknum, reason;
7936 
7937                 irPhysDisk = (Mpi2EventDataIrPhysicalDisk_t *)
7938                     eventreply->EventData;
7939                 physdisknum = ddi_get8(mpt->m_acc_reply_frame_hdl,
7940                     &irPhysDisk->PhysDiskNum);
7941                 devhandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7942                     &irPhysDisk->PhysDiskDevHandle);
7943                 enchandle = ddi_get16(mpt->m_acc_reply_frame_hdl,
7944                     &irPhysDisk->EnclosureHandle);
7945                 slot = ddi_get16(mpt->m_acc_reply_frame_hdl,
7946                     &irPhysDisk->Slot);
7947                 state = ddi_get32(mpt->m_acc_reply_frame_hdl,
7948                     &irPhysDisk->NewValue);
7949                 reason = ddi_get8(mpt->m_acc_reply_frame_hdl,
7950                     &irPhysDisk->ReasonCode);
7951 
7952                 NDBG20(("EVENT_IR_PHYSICAL_DISK event is received"));
7953 
7954                 switch (reason) {
7955                 case MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED:
7956                         mptsas_log(mpt, CE_NOTE,
7957                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7958                             "for enclosure with handle 0x%x is now in hot "
7959                             "spare pool %d",
7960                             physdisknum, devhandle, slot, enchandle,
7961                             (state >> 16) & 0xff);
7962                         break;
7963 
7964                 case MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED:
7965                         status = state;
7966                         mptsas_log(mpt, CE_NOTE,
7967                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7968                             "for enclosure with handle 0x%x is now "
7969                             "%s%s%s%s%s\n", physdisknum, devhandle, slot,
7970                             enchandle,
7971                             status & MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME
7972                             ? ", inactive" : ", active",
7973                             status & MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC
7974                             ? ", out of sync" : "",
7975                             status & MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED
7976                             ? ", quiesced" : "",
7977                             status &
7978                             MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED
7979                             ? ", write cache enabled" : "",
7980                             status & MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET
7981                             ? ", capacity expansion target" : "");
7982                         break;
7983 
7984                 case MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED:
7985                         mptsas_log(mpt, CE_NOTE,
7986                             " PhysDiskNum %d with DevHandle 0x%x in slot %d "
7987                             "for enclosure with handle 0x%x is now %s\n",
7988                             physdisknum, devhandle, slot, enchandle,
7989                             state == MPI2_RAID_PD_STATE_OPTIMAL
7990                             ? "optimal" :
7991                             state == MPI2_RAID_PD_STATE_REBUILDING
7992                             ? "rebuilding" :
7993                             state == MPI2_RAID_PD_STATE_DEGRADED
7994                             ? "degraded" :
7995                             state == MPI2_RAID_PD_STATE_HOT_SPARE
7996                             ? "a hot spare" :
7997                             state == MPI2_RAID_PD_STATE_ONLINE
7998                             ? "online" :
7999                             state == MPI2_RAID_PD_STATE_OFFLINE
8000                             ? "offline" :
8001                             state == MPI2_RAID_PD_STATE_NOT_COMPATIBLE
8002                             ? "not compatible" :
8003                             state == MPI2_RAID_PD_STATE_NOT_CONFIGURED
8004                             ? "not configured" :
8005                             "state unknown");
8006                         break;
8007                 }
8008                 break;
8009         }
8010         default:
8011                 NDBG20(("mptsas%d: unknown event %x received",
8012                     mpt->m_instance, event));
8013                 break;
8014         }
8015 
8016         /*
8017          * Return the reply frame to the free queue.
8018          */
8019         ddi_put32(mpt->m_acc_free_queue_hdl,
8020             &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index], rfm);
8021         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
8022             DDI_DMA_SYNC_FORDEV);
8023         if (++mpt->m_free_index == mpt->m_free_queue_depth) {
8024                 mpt->m_free_index = 0;
8025         }
8026         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
8027             mpt->m_free_index);
8028         mutex_exit(&mpt->m_mutex);
8029 }
8030 
8031 /*
8032  * invoked from timeout() to restart qfull cmds with throttle == 0
8033  */
8034 static void
8035 mptsas_restart_cmd(void *arg)
8036 {
8037         mptsas_t        *mpt = arg;
8038         mptsas_target_t *ptgt = NULL;
8039 
8040         mutex_enter(&mpt->m_mutex);
8041 
8042         mpt->m_restart_cmd_timeid = 0;
8043 
8044         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
8045             ptgt = refhash_next(mpt->m_targets, ptgt)) {
8046                 if (ptgt->m_reset_delay == 0) {
8047                         if (ptgt->m_t_throttle == QFULL_THROTTLE) {
8048                                 mptsas_set_throttle(mpt, ptgt,
8049                                     MAX_THROTTLE);
8050                         }
8051                 }
8052         }
8053         mptsas_restart_hba(mpt);
8054         mutex_exit(&mpt->m_mutex);
8055 }
8056 
8057 void
8058 mptsas_remove_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
8059 {
8060         int             slot;
8061         mptsas_slots_t  *slots = mpt->m_active;
8062         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8063 
8064         ASSERT(cmd != NULL);
8065         ASSERT(cmd->cmd_queued == FALSE);
8066 
8067         /*
8068          * Task Management cmds are removed in their own routines.  Also,
8069          * we don't want to modify timeout based on TM cmds.
8070          */
8071         if (cmd->cmd_flags & CFLAG_TM_CMD) {
8072                 return;
8073         }
8074 
8075         slot = cmd->cmd_slot;
8076 
8077         /*
8078          * remove the cmd.
8079          */
8080         if (cmd == slots->m_slot[slot]) {
8081                 NDBG31(("mptsas_remove_cmd: removing cmd=0x%p, flags "
8082                     "0x%x", (void *)cmd, cmd->cmd_flags));
8083                 slots->m_slot[slot] = NULL;
8084                 mpt->m_ncmds--;
8085 
8086                 /*
8087                  * only decrement per target ncmds if command
8088                  * has a target associated with it.
8089                  */
8090                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
8091                         ptgt->m_t_ncmds--;
8092                         /*
8093                          * reset throttle if we just ran an untagged command
8094                          * to a tagged target
8095                          */
8096                         if ((ptgt->m_t_ncmds == 0) &&
8097                             ((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0)) {
8098                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8099                         }
8100 
8101                         /*
8102                          * Remove this command from the active queue.
8103                          */
8104                         if (cmd->cmd_active_expiration != 0) {
8105                                 TAILQ_REMOVE(&ptgt->m_active_cmdq, cmd,
8106                                     cmd_active_link);
8107                                 cmd->cmd_active_expiration = 0;
8108                         }
8109                 }
8110         }
8111 
8112         /*
8113          * This is all we need to do for ioc commands.
8114          */
8115         if (cmd->cmd_flags & CFLAG_CMDIOC) {
8116                 mptsas_return_to_pool(mpt, cmd);
8117                 return;
8118         }
8119 
8120         ASSERT(cmd != slots->m_slot[cmd->cmd_slot]);
8121 }
8122 
8123 /*
8124  * accept all cmds on the tx_waitq if any and then
8125  * start a fresh request from the top of the device queue.
8126  *
8127  * since there are always cmds queued on the tx_waitq, and rare cmds on
8128  * the instance waitq, so this function should not be invoked in the ISR,
8129  * the mptsas_restart_waitq() is invoked in the ISR instead. otherwise, the
8130  * burden belongs to the IO dispatch CPUs is moved the interrupt CPU.
8131  */
8132 static void
8133 mptsas_restart_hba(mptsas_t *mpt)
8134 {
8135         ASSERT(mutex_owned(&mpt->m_mutex));
8136 
8137         mutex_enter(&mpt->m_tx_waitq_mutex);
8138         if (mpt->m_tx_waitq) {
8139                 mptsas_accept_tx_waitq(mpt);
8140         }
8141         mutex_exit(&mpt->m_tx_waitq_mutex);
8142         mptsas_restart_waitq(mpt);
8143 }
8144 
8145 /*
8146  * start a fresh request from the top of the device queue
8147  */
8148 static void
8149 mptsas_restart_waitq(mptsas_t *mpt)
8150 {
8151         mptsas_cmd_t    *cmd, *next_cmd;
8152         mptsas_target_t *ptgt = NULL;
8153 
8154         NDBG1(("mptsas_restart_waitq: mpt=0x%p", (void *)mpt));
8155 
8156         ASSERT(mutex_owned(&mpt->m_mutex));
8157 
8158         /*
8159          * If there is a reset delay, don't start any cmds.  Otherwise, start
8160          * as many cmds as possible.
8161          * Since SMID 0 is reserved and the TM slot is reserved, the actual max
8162          * commands is m_max_requests - 2.
8163          */
8164         cmd = mpt->m_waitq;
8165 
8166         while (cmd != NULL) {
8167                 next_cmd = cmd->cmd_linkp;
8168                 if (cmd->cmd_flags & CFLAG_PASSTHRU) {
8169                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8170                                 /*
8171                                  * passthru command get slot need
8172                                  * set CFLAG_PREPARED.
8173                                  */
8174                                 cmd->cmd_flags |= CFLAG_PREPARED;
8175                                 mptsas_waitq_delete(mpt, cmd);
8176                                 mptsas_start_passthru(mpt, cmd);
8177                         }
8178                         cmd = next_cmd;
8179                         continue;
8180                 }
8181                 if (cmd->cmd_flags & CFLAG_CONFIG) {
8182                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8183                                 /*
8184                                  * Send the config page request and delete it
8185                                  * from the waitq.
8186                                  */
8187                                 cmd->cmd_flags |= CFLAG_PREPARED;
8188                                 mptsas_waitq_delete(mpt, cmd);
8189                                 mptsas_start_config_page_access(mpt, cmd);
8190                         }
8191                         cmd = next_cmd;
8192                         continue;
8193                 }
8194                 if (cmd->cmd_flags & CFLAG_FW_DIAG) {
8195                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8196                                 /*
8197                                  * Send the FW Diag request and delete if from
8198                                  * the waitq.
8199                                  */
8200                                 cmd->cmd_flags |= CFLAG_PREPARED;
8201                                 mptsas_waitq_delete(mpt, cmd);
8202                                 mptsas_start_diag(mpt, cmd);
8203                         }
8204                         cmd = next_cmd;
8205                         continue;
8206                 }
8207 
8208                 ptgt = cmd->cmd_tgt_addr;
8209                 if (ptgt && (ptgt->m_t_throttle == DRAIN_THROTTLE) &&
8210                     (ptgt->m_t_ncmds == 0)) {
8211                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
8212                 }
8213                 if ((mpt->m_ncmds <= (mpt->m_max_requests - 2)) &&
8214                     (ptgt && (ptgt->m_reset_delay == 0)) &&
8215                     (ptgt && (ptgt->m_t_ncmds <
8216                     ptgt->m_t_throttle))) {
8217                         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
8218                                 mptsas_waitq_delete(mpt, cmd);
8219                                 (void) mptsas_start_cmd(mpt, cmd);
8220                         }
8221                 }
8222                 cmd = next_cmd;
8223         }
8224 }
8225 /*
8226  * Cmds are queued if tran_start() doesn't get the m_mutexlock(no wait).
8227  * Accept all those queued cmds before new cmd is accept so that the
8228  * cmds are sent in order.
8229  */
8230 static void
8231 mptsas_accept_tx_waitq(mptsas_t *mpt)
8232 {
8233         mptsas_cmd_t *cmd;
8234 
8235         ASSERT(mutex_owned(&mpt->m_mutex));
8236         ASSERT(mutex_owned(&mpt->m_tx_waitq_mutex));
8237 
8238         /*
8239          * A Bus Reset could occur at any time and flush the tx_waitq,
8240          * so we cannot count on the tx_waitq to contain even one cmd.
8241          * And when the m_tx_waitq_mutex is released and run
8242          * mptsas_accept_pkt(), the tx_waitq may be flushed.
8243          */
8244         cmd = mpt->m_tx_waitq;
8245         for (;;) {
8246                 if ((cmd = mpt->m_tx_waitq) == NULL) {
8247                         mpt->m_tx_draining = 0;
8248                         break;
8249                 }
8250                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL) {
8251                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8252                 }
8253                 cmd->cmd_linkp = NULL;
8254                 mutex_exit(&mpt->m_tx_waitq_mutex);
8255                 if (mptsas_accept_pkt(mpt, cmd) != TRAN_ACCEPT)
8256                         cmn_err(CE_WARN, "mpt: mptsas_accept_tx_waitq: failed "
8257                             "to accept cmd on queue\n");
8258                 mutex_enter(&mpt->m_tx_waitq_mutex);
8259         }
8260 }
8261 
8262 
8263 /*
8264  * mpt tag type lookup
8265  */
8266 static char mptsas_tag_lookup[] =
8267         {0, MSG_HEAD_QTAG, MSG_ORDERED_QTAG, 0, MSG_SIMPLE_QTAG};
8268 
8269 static int
8270 mptsas_start_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
8271 {
8272         struct scsi_pkt         *pkt = CMD2PKT(cmd);
8273         uint32_t                control = 0;
8274         caddr_t                 mem;
8275         pMpi2SCSIIORequest_t    io_request;
8276         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
8277         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
8278         mptsas_target_t         *ptgt = cmd->cmd_tgt_addr;
8279         uint16_t                SMID, io_flags = 0;
8280         uint32_t                request_desc_low, request_desc_high;
8281         mptsas_cmd_t            *c;
8282 
8283         NDBG1(("mptsas_start_cmd: cmd=0x%p, flags 0x%x", (void *)cmd,
8284             cmd->cmd_flags));
8285 
8286         /*
8287          * Set SMID and increment index.  Rollover to 1 instead of 0 if index
8288          * is at the max.  0 is an invalid SMID, so we call the first index 1.
8289          */
8290         SMID = cmd->cmd_slot;
8291 
8292         /*
8293          * It is possible for back to back device reset to
8294          * happen before the reset delay has expired.  That's
8295          * ok, just let the device reset go out on the bus.
8296          */
8297         if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8298                 ASSERT(ptgt->m_reset_delay == 0);
8299         }
8300 
8301         /*
8302          * if a non-tagged cmd is submitted to an active tagged target
8303          * then drain before submitting this cmd; SCSI-2 allows RQSENSE
8304          * to be untagged
8305          */
8306         if (((cmd->cmd_pkt_flags & FLAG_TAGMASK) == 0) &&
8307             (ptgt->m_t_ncmds > 1) &&
8308             ((cmd->cmd_flags & CFLAG_TM_CMD) == 0) &&
8309             (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE)) {
8310                 if ((cmd->cmd_pkt_flags & FLAG_NOINTR) == 0) {
8311                         NDBG23(("target=%d, untagged cmd, start draining\n",
8312                             ptgt->m_devhdl));
8313 
8314                         if (ptgt->m_reset_delay == 0) {
8315                                 mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
8316                         }
8317 
8318                         mptsas_remove_cmd(mpt, cmd);
8319                         cmd->cmd_pkt_flags |= FLAG_HEAD;
8320                         mptsas_waitq_add(mpt, cmd);
8321                 }
8322                 return (DDI_FAILURE);
8323         }
8324 
8325         /*
8326          * Set correct tag bits.
8327          */
8328         if (cmd->cmd_pkt_flags & FLAG_TAGMASK) {
8329                 switch (mptsas_tag_lookup[((cmd->cmd_pkt_flags &
8330                     FLAG_TAGMASK) >> 12)]) {
8331                 case MSG_SIMPLE_QTAG:
8332                         control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8333                         break;
8334                 case MSG_HEAD_QTAG:
8335                         control |= MPI2_SCSIIO_CONTROL_HEADOFQ;
8336                         break;
8337                 case MSG_ORDERED_QTAG:
8338                         control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
8339                         break;
8340                 default:
8341                         mptsas_log(mpt, CE_WARN, "mpt: Invalid tag type\n");
8342                         break;
8343                 }
8344         } else {
8345                 if (*(cmd->cmd_pkt->pkt_cdbp) != SCMD_REQUEST_SENSE) {
8346                                 ptgt->m_t_throttle = 1;
8347                 }
8348                 control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
8349         }
8350 
8351         if (cmd->cmd_pkt_flags & FLAG_TLR) {
8352                 control |= MPI2_SCSIIO_CONTROL_TLR_ON;
8353         }
8354 
8355         mem = mpt->m_req_frame + (mpt->m_req_frame_size * SMID);
8356         io_request = (pMpi2SCSIIORequest_t)mem;
8357 
8358         bzero(io_request, sizeof (Mpi2SCSIIORequest_t));
8359         ddi_put8(acc_hdl, &io_request->SGLOffset0, offsetof
8360             (MPI2_SCSI_IO_REQUEST, SGL) / 4);
8361         mptsas_init_std_hdr(acc_hdl, io_request, ptgt->m_devhdl, Lun(cmd), 0,
8362             MPI2_FUNCTION_SCSI_IO_REQUEST);
8363 
8364         (void) ddi_rep_put8(acc_hdl, (uint8_t *)pkt->pkt_cdbp,
8365             io_request->CDB.CDB32, cmd->cmd_cdblen, DDI_DEV_AUTOINCR);
8366 
8367         io_flags = cmd->cmd_cdblen;
8368         if (mptsas_use_fastpath &&
8369             ptgt->m_io_flags & MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH) {
8370                 io_flags |= MPI25_SCSIIO_IOFLAGS_FAST_PATH;
8371                 request_desc_low = MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO;
8372         } else {
8373                 request_desc_low = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
8374         }
8375         ddi_put16(acc_hdl, &io_request->IoFlags, io_flags);
8376         /*
8377          * setup the Scatter/Gather DMA list for this request
8378          */
8379         if (cmd->cmd_cookiec > 0) {
8380                 mptsas_sge_setup(mpt, cmd, &control, io_request, acc_hdl);
8381         } else {
8382                 ddi_put32(acc_hdl, &io_request->SGL.MpiSimple.FlagsLength,
8383                     ((uint32_t)MPI2_SGE_FLAGS_LAST_ELEMENT |
8384                     MPI2_SGE_FLAGS_END_OF_BUFFER |
8385                     MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
8386                     MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT);
8387         }
8388 
8389         /*
8390          * save ARQ information
8391          */
8392         ddi_put8(acc_hdl, &io_request->SenseBufferLength, cmd->cmd_rqslen);
8393         if ((cmd->cmd_flags & (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) ==
8394             (CFLAG_SCBEXTERN | CFLAG_EXTARQBUFVALID)) {
8395                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8396                     cmd->cmd_ext_arqcookie.dmac_address);
8397         } else {
8398                 ddi_put32(acc_hdl, &io_request->SenseBufferLowAddress,
8399                     cmd->cmd_arqcookie.dmac_address);
8400         }
8401 
8402         ddi_put32(acc_hdl, &io_request->Control, control);
8403 
8404         NDBG31(("starting message=%d(0x%p), with cmd=0x%p",
8405             SMID, (void *)io_request, (void *)cmd));
8406 
8407         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
8408 
8409         /*
8410          * Build request descriptor and write it to the request desc post reg.
8411          */
8412         request_desc_low |= (SMID << 16);
8413         request_desc_high = ptgt->m_devhdl << 16;
8414         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
8415 
8416         /*
8417          * Start timeout.
8418          */
8419         cmd->cmd_active_expiration =
8420             gethrtime() + (hrtime_t)pkt->pkt_time * NANOSEC;
8421 #ifdef MPTSAS_TEST
8422         /*
8423          * Force timeouts to happen immediately.
8424          */
8425         if (mptsas_test_timeouts)
8426                 cmd->cmd_active_expiration = gethrtime();
8427 #endif
8428         c = TAILQ_FIRST(&ptgt->m_active_cmdq);
8429         if (c == NULL ||
8430             c->cmd_active_expiration < cmd->cmd_active_expiration) {
8431                 /*
8432                  * Common case is that this is the last pending expiration
8433                  * (or queue is empty). Insert at head of the queue.
8434                  */
8435                 TAILQ_INSERT_HEAD(&ptgt->m_active_cmdq, cmd, cmd_active_link);
8436         } else {
8437                 /*
8438                  * Queue is not empty and first element expires later than
8439                  * this command. Search for element expiring sooner.
8440                  */
8441                 while ((c = TAILQ_NEXT(c, cmd_active_link)) != NULL) {
8442                         if (c->cmd_active_expiration <
8443                             cmd->cmd_active_expiration) {
8444                                 TAILQ_INSERT_BEFORE(c, cmd, cmd_active_link);
8445                                 break;
8446                         }
8447                 }
8448                 if (c == NULL) {
8449                         /*
8450                          * No element found expiring sooner, append to
8451                          * non-empty queue.
8452                          */
8453                         TAILQ_INSERT_TAIL(&ptgt->m_active_cmdq, cmd,
8454                             cmd_active_link);
8455                 }
8456         }
8457 
8458         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
8459             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
8460                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8461                 return (DDI_FAILURE);
8462         }
8463         return (DDI_SUCCESS);
8464 }
8465 
8466 /*
8467  * Select a helper thread to handle current doneq
8468  */
8469 static void
8470 mptsas_deliver_doneq_thread(mptsas_t *mpt)
8471 {
8472         uint64_t                        t, i;
8473         uint32_t                        min = 0xffffffff;
8474         mptsas_doneq_thread_list_t      *item;
8475 
8476         for (i = 0; i < mpt->m_doneq_thread_n; i++) {
8477                 item = &mpt->m_doneq_thread_id[i];
8478                 /*
8479                  * If the completed command on help thread[i] less than
8480                  * doneq_thread_threshold, then pick the thread[i]. Otherwise
8481                  * pick a thread which has least completed command.
8482                  */
8483 
8484                 mutex_enter(&item->mutex);
8485                 if (item->len < mpt->m_doneq_thread_threshold) {
8486                         t = i;
8487                         mutex_exit(&item->mutex);
8488                         break;
8489                 }
8490                 if (item->len < min) {
8491                         min = item->len;
8492                         t = i;
8493                 }
8494                 mutex_exit(&item->mutex);
8495         }
8496         mutex_enter(&mpt->m_doneq_thread_id[t].mutex);
8497         mptsas_doneq_mv(mpt, t);
8498         cv_signal(&mpt->m_doneq_thread_id[t].cv);
8499         mutex_exit(&mpt->m_doneq_thread_id[t].mutex);
8500 }
8501 
8502 /*
8503  * move the current global doneq to the doneq of thead[t]
8504  */
8505 static void
8506 mptsas_doneq_mv(mptsas_t *mpt, uint64_t t)
8507 {
8508         mptsas_cmd_t                    *cmd;
8509         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8510 
8511         ASSERT(mutex_owned(&item->mutex));
8512         while ((cmd = mpt->m_doneq) != NULL) {
8513                 if ((mpt->m_doneq = cmd->cmd_linkp) == NULL) {
8514                         mpt->m_donetail = &mpt->m_doneq;
8515                 }
8516                 cmd->cmd_linkp = NULL;
8517                 *item->donetail = cmd;
8518                 item->donetail = &cmd->cmd_linkp;
8519                 mpt->m_doneq_len--;
8520                 item->len++;
8521         }
8522 }
8523 
8524 void
8525 mptsas_fma_check(mptsas_t *mpt, mptsas_cmd_t *cmd)
8526 {
8527         struct scsi_pkt *pkt = CMD2PKT(cmd);
8528 
8529         /* Check all acc and dma handles */
8530         if ((mptsas_check_acc_handle(mpt->m_datap) !=
8531             DDI_SUCCESS) ||
8532             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
8533             DDI_SUCCESS) ||
8534             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
8535             DDI_SUCCESS) ||
8536             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
8537             DDI_SUCCESS) ||
8538             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
8539             DDI_SUCCESS) ||
8540             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
8541             DDI_SUCCESS) ||
8542             (mptsas_check_acc_handle(mpt->m_config_handle) !=
8543             DDI_SUCCESS)) {
8544                 ddi_fm_service_impact(mpt->m_dip,
8545                     DDI_SERVICE_UNAFFECTED);
8546                 ddi_fm_acc_err_clear(mpt->m_config_handle,
8547                     DDI_FME_VER0);
8548                 pkt->pkt_reason = CMD_TRAN_ERR;
8549                 pkt->pkt_statistics = 0;
8550         }
8551         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
8552             DDI_SUCCESS) ||
8553             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
8554             DDI_SUCCESS) ||
8555             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
8556             DDI_SUCCESS) ||
8557             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
8558             DDI_SUCCESS) ||
8559             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
8560             DDI_SUCCESS)) {
8561                 ddi_fm_service_impact(mpt->m_dip,
8562                     DDI_SERVICE_UNAFFECTED);
8563                 pkt->pkt_reason = CMD_TRAN_ERR;
8564                 pkt->pkt_statistics = 0;
8565         }
8566         if (cmd->cmd_dmahandle &&
8567             (mptsas_check_dma_handle(cmd->cmd_dmahandle) != DDI_SUCCESS)) {
8568                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8569                 pkt->pkt_reason = CMD_TRAN_ERR;
8570                 pkt->pkt_statistics = 0;
8571         }
8572         if ((cmd->cmd_extra_frames &&
8573             ((mptsas_check_dma_handle(cmd->cmd_extra_frames->m_dma_hdl) !=
8574             DDI_SUCCESS) ||
8575             (mptsas_check_acc_handle(cmd->cmd_extra_frames->m_acc_hdl) !=
8576             DDI_SUCCESS)))) {
8577                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8578                 pkt->pkt_reason = CMD_TRAN_ERR;
8579                 pkt->pkt_statistics = 0;
8580         }
8581         if (cmd->cmd_arqhandle &&
8582             (mptsas_check_dma_handle(cmd->cmd_arqhandle) != DDI_SUCCESS)) {
8583                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8584                 pkt->pkt_reason = CMD_TRAN_ERR;
8585                 pkt->pkt_statistics = 0;
8586         }
8587         if (cmd->cmd_ext_arqhandle &&
8588             (mptsas_check_dma_handle(cmd->cmd_ext_arqhandle) != DDI_SUCCESS)) {
8589                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
8590                 pkt->pkt_reason = CMD_TRAN_ERR;
8591                 pkt->pkt_statistics = 0;
8592         }
8593 }
8594 
8595 /*
8596  * These routines manipulate the queue of commands that
8597  * are waiting for their completion routines to be called.
8598  * The queue is usually in FIFO order but on an MP system
8599  * it's possible for the completion routines to get out
8600  * of order. If that's a problem you need to add a global
8601  * mutex around the code that calls the completion routine
8602  * in the interrupt handler.
8603  */
8604 static void
8605 mptsas_doneq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8606 {
8607         struct scsi_pkt *pkt = CMD2PKT(cmd);
8608 
8609         NDBG31(("mptsas_doneq_add: cmd=0x%p", (void *)cmd));
8610 
8611         ASSERT((cmd->cmd_flags & CFLAG_COMPLETED) == 0);
8612         cmd->cmd_linkp = NULL;
8613         cmd->cmd_flags |= CFLAG_FINISHED;
8614         cmd->cmd_flags &= ~CFLAG_IN_TRANSPORT;
8615 
8616         mptsas_fma_check(mpt, cmd);
8617 
8618         /*
8619          * only add scsi pkts that have completion routines to
8620          * the doneq.  no intr cmds do not have callbacks.
8621          */
8622         if (pkt && (pkt->pkt_comp)) {
8623                 *mpt->m_donetail = cmd;
8624                 mpt->m_donetail = &cmd->cmd_linkp;
8625                 mpt->m_doneq_len++;
8626         }
8627 }
8628 
8629 static mptsas_cmd_t *
8630 mptsas_doneq_thread_rm(mptsas_t *mpt, uint64_t t)
8631 {
8632         mptsas_cmd_t                    *cmd;
8633         mptsas_doneq_thread_list_t      *item = &mpt->m_doneq_thread_id[t];
8634 
8635         /* pop one off the done queue */
8636         if ((cmd = item->doneq) != NULL) {
8637                 /* if the queue is now empty fix the tail pointer */
8638                 NDBG31(("mptsas_doneq_thread_rm: cmd=0x%p", (void *)cmd));
8639                 if ((item->doneq = cmd->cmd_linkp) == NULL) {
8640                         item->donetail = &item->doneq;
8641                 }
8642                 cmd->cmd_linkp = NULL;
8643                 item->len--;
8644         }
8645         return (cmd);
8646 }
8647 
8648 static void
8649 mptsas_doneq_empty(mptsas_t *mpt)
8650 {
8651         if (mpt->m_doneq && !mpt->m_in_callback) {
8652                 mptsas_cmd_t    *cmd, *next;
8653                 struct scsi_pkt *pkt;
8654 
8655                 mpt->m_in_callback = 1;
8656                 cmd = mpt->m_doneq;
8657                 mpt->m_doneq = NULL;
8658                 mpt->m_donetail = &mpt->m_doneq;
8659                 mpt->m_doneq_len = 0;
8660 
8661                 mutex_exit(&mpt->m_mutex);
8662                 /*
8663                  * run the completion routines of all the
8664                  * completed commands
8665                  */
8666                 while (cmd != NULL) {
8667                         next = cmd->cmd_linkp;
8668                         cmd->cmd_linkp = NULL;
8669                         /* run this command's completion routine */
8670                         cmd->cmd_flags |= CFLAG_COMPLETED;
8671                         pkt = CMD2PKT(cmd);
8672                         mptsas_pkt_comp(pkt, cmd);
8673                         cmd = next;
8674                 }
8675                 mutex_enter(&mpt->m_mutex);
8676                 mpt->m_in_callback = 0;
8677         }
8678 }
8679 
8680 /*
8681  * These routines manipulate the target's queue of pending requests
8682  */
8683 void
8684 mptsas_waitq_add(mptsas_t *mpt, mptsas_cmd_t *cmd)
8685 {
8686         NDBG7(("mptsas_waitq_add: cmd=0x%p", (void *)cmd));
8687         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8688         cmd->cmd_queued = TRUE;
8689         if (ptgt)
8690                 ptgt->m_t_nwait++;
8691         if (cmd->cmd_pkt_flags & FLAG_HEAD) {
8692                 if ((cmd->cmd_linkp = mpt->m_waitq) == NULL) {
8693                         mpt->m_waitqtail = &cmd->cmd_linkp;
8694                 }
8695                 mpt->m_waitq = cmd;
8696         } else {
8697                 cmd->cmd_linkp = NULL;
8698                 *(mpt->m_waitqtail) = cmd;
8699                 mpt->m_waitqtail = &cmd->cmd_linkp;
8700         }
8701 }
8702 
8703 static mptsas_cmd_t *
8704 mptsas_waitq_rm(mptsas_t *mpt)
8705 {
8706         mptsas_cmd_t    *cmd;
8707         mptsas_target_t *ptgt;
8708         NDBG7(("mptsas_waitq_rm"));
8709 
8710         MPTSAS_WAITQ_RM(mpt, cmd);
8711 
8712         NDBG7(("mptsas_waitq_rm: cmd=0x%p", (void *)cmd));
8713         if (cmd) {
8714                 ptgt = cmd->cmd_tgt_addr;
8715                 if (ptgt) {
8716                         ptgt->m_t_nwait--;
8717                         ASSERT(ptgt->m_t_nwait >= 0);
8718                 }
8719         }
8720         return (cmd);
8721 }
8722 
8723 /*
8724  * remove specified cmd from the middle of the wait queue.
8725  */
8726 static void
8727 mptsas_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8728 {
8729         mptsas_cmd_t    *prevp = mpt->m_waitq;
8730         mptsas_target_t *ptgt = cmd->cmd_tgt_addr;
8731 
8732         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8733             (void *)mpt, (void *)cmd));
8734         if (ptgt) {
8735                 ptgt->m_t_nwait--;
8736                 ASSERT(ptgt->m_t_nwait >= 0);
8737         }
8738 
8739         if (prevp == cmd) {
8740                 if ((mpt->m_waitq = cmd->cmd_linkp) == NULL)
8741                         mpt->m_waitqtail = &mpt->m_waitq;
8742 
8743                 cmd->cmd_linkp = NULL;
8744                 cmd->cmd_queued = FALSE;
8745                 NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8746                     (void *)mpt, (void *)cmd));
8747                 return;
8748         }
8749 
8750         while (prevp != NULL) {
8751                 if (prevp->cmd_linkp == cmd) {
8752                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8753                                 mpt->m_waitqtail = &prevp->cmd_linkp;
8754 
8755                         cmd->cmd_linkp = NULL;
8756                         cmd->cmd_queued = FALSE;
8757                         NDBG7(("mptsas_waitq_delete: mpt=0x%p cmd=0x%p",
8758                             (void *)mpt, (void *)cmd));
8759                         return;
8760                 }
8761                 prevp = prevp->cmd_linkp;
8762         }
8763         cmn_err(CE_PANIC, "mpt: mptsas_waitq_delete: queue botch");
8764 }
8765 
8766 static mptsas_cmd_t *
8767 mptsas_tx_waitq_rm(mptsas_t *mpt)
8768 {
8769         mptsas_cmd_t *cmd;
8770         NDBG7(("mptsas_tx_waitq_rm"));
8771 
8772         MPTSAS_TX_WAITQ_RM(mpt, cmd);
8773 
8774         NDBG7(("mptsas_tx_waitq_rm: cmd=0x%p", (void *)cmd));
8775 
8776         return (cmd);
8777 }
8778 
8779 /*
8780  * remove specified cmd from the middle of the tx_waitq.
8781  */
8782 static void
8783 mptsas_tx_waitq_delete(mptsas_t *mpt, mptsas_cmd_t *cmd)
8784 {
8785         mptsas_cmd_t *prevp = mpt->m_tx_waitq;
8786 
8787         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8788             (void *)mpt, (void *)cmd));
8789 
8790         if (prevp == cmd) {
8791                 if ((mpt->m_tx_waitq = cmd->cmd_linkp) == NULL)
8792                         mpt->m_tx_waitqtail = &mpt->m_tx_waitq;
8793 
8794                 cmd->cmd_linkp = NULL;
8795                 cmd->cmd_queued = FALSE;
8796                 NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8797                     (void *)mpt, (void *)cmd));
8798                 return;
8799         }
8800 
8801         while (prevp != NULL) {
8802                 if (prevp->cmd_linkp == cmd) {
8803                         if ((prevp->cmd_linkp = cmd->cmd_linkp) == NULL)
8804                                 mpt->m_tx_waitqtail = &prevp->cmd_linkp;
8805 
8806                         cmd->cmd_linkp = NULL;
8807                         cmd->cmd_queued = FALSE;
8808                         NDBG7(("mptsas_tx_waitq_delete: mpt=0x%p cmd=0x%p",
8809                             (void *)mpt, (void *)cmd));
8810                         return;
8811                 }
8812                 prevp = prevp->cmd_linkp;
8813         }
8814         cmn_err(CE_PANIC, "mpt: mptsas_tx_waitq_delete: queue botch");
8815 }
8816 
8817 /*
8818  * device and bus reset handling
8819  *
8820  * Notes:
8821  *      - RESET_ALL:    reset the controller
8822  *      - RESET_TARGET: reset the target specified in scsi_address
8823  */
8824 static int
8825 mptsas_scsi_reset(struct scsi_address *ap, int level)
8826 {
8827         mptsas_t                *mpt = ADDR2MPT(ap);
8828         int                     rval;
8829         mptsas_tgt_private_t    *tgt_private;
8830         mptsas_target_t         *ptgt = NULL;
8831 
8832         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->tran_tgt_private;
8833         ptgt = tgt_private->t_private;
8834         if (ptgt == NULL) {
8835                 return (FALSE);
8836         }
8837         NDBG22(("mptsas_scsi_reset: target=%d level=%d", ptgt->m_devhdl,
8838             level));
8839 
8840         mutex_enter(&mpt->m_mutex);
8841         /*
8842          * if we are not in panic set up a reset delay for this target
8843          */
8844         if (!ddi_in_panic()) {
8845                 mptsas_setup_bus_reset_delay(mpt);
8846         } else {
8847                 drv_usecwait(mpt->m_scsi_reset_delay * 1000);
8848         }
8849         rval = mptsas_do_scsi_reset(mpt, ptgt->m_devhdl);
8850         mutex_exit(&mpt->m_mutex);
8851 
8852         /*
8853          * The transport layer expect to only see TRUE and
8854          * FALSE. Therefore, we will adjust the return value
8855          * if mptsas_do_scsi_reset returns FAILED.
8856          */
8857         if (rval == FAILED)
8858                 rval = FALSE;
8859         return (rval);
8860 }
8861 
8862 static int
8863 mptsas_do_scsi_reset(mptsas_t *mpt, uint16_t devhdl)
8864 {
8865         int             rval = FALSE;
8866         uint8_t         config, disk;
8867 
8868         ASSERT(mutex_owned(&mpt->m_mutex));
8869 
8870         if (mptsas_debug_resets) {
8871                 mptsas_log(mpt, CE_WARN, "mptsas_do_scsi_reset: target=%d",
8872                     devhdl);
8873         }
8874 
8875         /*
8876          * Issue a Target Reset message to the target specified but not to a
8877          * disk making up a raid volume.  Just look through the RAID config
8878          * Phys Disk list of DevHandles.  If the target's DevHandle is in this
8879          * list, then don't reset this target.
8880          */
8881         for (config = 0; config < mpt->m_num_raid_configs; config++) {
8882                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
8883                         if (devhdl == mpt->m_raidconfig[config].
8884                             m_physdisk_devhdl[disk]) {
8885                                 return (TRUE);
8886                         }
8887                 }
8888         }
8889 
8890         rval = mptsas_ioc_task_management(mpt,
8891             MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, devhdl, 0, NULL, 0, 0);
8892 
8893         mptsas_doneq_empty(mpt);
8894         return (rval);
8895 }
8896 
8897 static int
8898 mptsas_scsi_reset_notify(struct scsi_address *ap, int flag,
8899         void (*callback)(caddr_t), caddr_t arg)
8900 {
8901         mptsas_t        *mpt = ADDR2MPT(ap);
8902 
8903         NDBG22(("mptsas_scsi_reset_notify: tgt=%d", ap->a_target));
8904 
8905         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
8906             &mpt->m_mutex, &mpt->m_reset_notify_listf));
8907 }
8908 
8909 static int
8910 mptsas_get_name(struct scsi_device *sd, char *name, int len)
8911 {
8912         dev_info_t      *lun_dip = NULL;
8913 
8914         ASSERT(sd != NULL);
8915         ASSERT(name != NULL);
8916         lun_dip = sd->sd_dev;
8917         ASSERT(lun_dip != NULL);
8918 
8919         if (mptsas_name_child(lun_dip, name, len) == DDI_SUCCESS) {
8920                 return (1);
8921         } else {
8922                 return (0);
8923         }
8924 }
8925 
8926 static int
8927 mptsas_get_bus_addr(struct scsi_device *sd, char *name, int len)
8928 {
8929         return (mptsas_get_name(sd, name, len));
8930 }
8931 
8932 void
8933 mptsas_set_throttle(mptsas_t *mpt, mptsas_target_t *ptgt, int what)
8934 {
8935 
8936         NDBG25(("mptsas_set_throttle: throttle=%x", what));
8937 
8938         /*
8939          * if the bus is draining/quiesced, no changes to the throttles
8940          * are allowed. Not allowing change of throttles during draining
8941          * limits error recovery but will reduce draining time
8942          *
8943          * all throttles should have been set to HOLD_THROTTLE
8944          */
8945         if (mpt->m_softstate & (MPTSAS_SS_QUIESCED | MPTSAS_SS_DRAINING)) {
8946                 return;
8947         }
8948 
8949         if (what == HOLD_THROTTLE) {
8950                 ptgt->m_t_throttle = HOLD_THROTTLE;
8951         } else if (ptgt->m_reset_delay == 0) {
8952                 ptgt->m_t_throttle = what;
8953         }
8954 }
8955 
8956 /*
8957  * Clean up from a device reset.
8958  * For the case of target reset, this function clears the waitq of all
8959  * commands for a particular target.   For the case of abort task set, this
8960  * function clears the waitq of all commonds for a particular target/lun.
8961  */
8962 static void
8963 mptsas_flush_target(mptsas_t *mpt, ushort_t target, int lun, uint8_t tasktype)
8964 {
8965         mptsas_slots_t  *slots = mpt->m_active;
8966         mptsas_cmd_t    *cmd, *next_cmd;
8967         int             slot;
8968         uchar_t         reason;
8969         uint_t          stat;
8970         hrtime_t        timestamp;
8971 
8972         NDBG25(("mptsas_flush_target: target=%d lun=%d", target, lun));
8973 
8974         timestamp = gethrtime();
8975 
8976         /*
8977          * Make sure the I/O Controller has flushed all cmds
8978          * that are associated with this target for a target reset
8979          * and target/lun for abort task set.
8980          * Account for TM requests, which use the last SMID.
8981          */
8982         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
8983                 if ((cmd = slots->m_slot[slot]) == NULL)
8984                         continue;
8985                 reason = CMD_RESET;
8986                 stat = STAT_DEV_RESET;
8987                 switch (tasktype) {
8988                 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
8989                         if (Tgt(cmd) == target) {
8990                                 if (cmd->cmd_active_expiration <= timestamp) {
8991                                         /*
8992                                          * When timeout requested, propagate
8993                                          * proper reason and statistics to
8994                                          * target drivers.
8995                                          */
8996                                         reason = CMD_TIMEOUT;
8997                                         stat |= STAT_TIMEOUT;
8998                                 }
8999                                 NDBG25(("mptsas_flush_target discovered non-"
9000                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9001                                     tasktype));
9002                                 mptsas_dump_cmd(mpt, cmd);
9003                                 mptsas_remove_cmd(mpt, cmd);
9004                                 mptsas_set_pkt_reason(mpt, cmd, reason, stat);
9005                                 mptsas_doneq_add(mpt, cmd);
9006                         }
9007                         break;
9008                 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9009                         reason = CMD_ABORTED;
9010                         stat = STAT_ABORTED;
9011                         /*FALLTHROUGH*/
9012                 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9013                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9014 
9015                                 NDBG25(("mptsas_flush_target discovered non-"
9016                                     "NULL cmd in slot %d, tasktype 0x%x", slot,
9017                                     tasktype));
9018                                 mptsas_dump_cmd(mpt, cmd);
9019                                 mptsas_remove_cmd(mpt, cmd);
9020                                 mptsas_set_pkt_reason(mpt, cmd, reason,
9021                                     stat);
9022                                 mptsas_doneq_add(mpt, cmd);
9023                         }
9024                         break;
9025                 default:
9026                         break;
9027                 }
9028         }
9029 
9030         /*
9031          * Flush the waitq and tx_waitq of this target's cmds
9032          */
9033         cmd = mpt->m_waitq;
9034 
9035         reason = CMD_RESET;
9036         stat = STAT_DEV_RESET;
9037 
9038         switch (tasktype) {
9039         case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
9040                 while (cmd != NULL) {
9041                         next_cmd = cmd->cmd_linkp;
9042                         if (Tgt(cmd) == target) {
9043                                 mptsas_waitq_delete(mpt, cmd);
9044                                 mptsas_set_pkt_reason(mpt, cmd,
9045                                     reason, stat);
9046                                 mptsas_doneq_add(mpt, cmd);
9047                         }
9048                         cmd = next_cmd;
9049                 }
9050                 mutex_enter(&mpt->m_tx_waitq_mutex);
9051                 cmd = mpt->m_tx_waitq;
9052                 while (cmd != NULL) {
9053                         next_cmd = cmd->cmd_linkp;
9054                         if (Tgt(cmd) == target) {
9055                                 mptsas_tx_waitq_delete(mpt, cmd);
9056                                 mutex_exit(&mpt->m_tx_waitq_mutex);
9057                                 mptsas_set_pkt_reason(mpt, cmd,
9058                                     reason, stat);
9059                                 mptsas_doneq_add(mpt, cmd);
9060                                 mutex_enter(&mpt->m_tx_waitq_mutex);
9061                         }
9062                         cmd = next_cmd;
9063                 }
9064                 mutex_exit(&mpt->m_tx_waitq_mutex);
9065                 break;
9066         case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
9067                 reason = CMD_ABORTED;
9068                 stat =  STAT_ABORTED;
9069                 /*FALLTHROUGH*/
9070         case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
9071                 while (cmd != NULL) {
9072                         next_cmd = cmd->cmd_linkp;
9073                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9074                                 mptsas_waitq_delete(mpt, cmd);
9075                                 mptsas_set_pkt_reason(mpt, cmd,
9076                                     reason, stat);
9077                                 mptsas_doneq_add(mpt, cmd);
9078                         }
9079                         cmd = next_cmd;
9080                 }
9081                 mutex_enter(&mpt->m_tx_waitq_mutex);
9082                 cmd = mpt->m_tx_waitq;
9083                 while (cmd != NULL) {
9084                         next_cmd = cmd->cmd_linkp;
9085                         if ((Tgt(cmd) == target) && (Lun(cmd) == lun)) {
9086                                 mptsas_tx_waitq_delete(mpt, cmd);
9087                                 mutex_exit(&mpt->m_tx_waitq_mutex);
9088                                 mptsas_set_pkt_reason(mpt, cmd,
9089                                     reason, stat);
9090                                 mptsas_doneq_add(mpt, cmd);
9091                                 mutex_enter(&mpt->m_tx_waitq_mutex);
9092                         }
9093                         cmd = next_cmd;
9094                 }
9095                 mutex_exit(&mpt->m_tx_waitq_mutex);
9096                 break;
9097         default:
9098                 mptsas_log(mpt, CE_WARN, "Unknown task management type %d.",
9099                     tasktype);
9100                 break;
9101         }
9102 }
9103 
9104 /*
9105  * Clean up hba state, abort all outstanding command and commands in waitq
9106  * reset timeout of all targets.
9107  */
9108 static void
9109 mptsas_flush_hba(mptsas_t *mpt)
9110 {
9111         mptsas_slots_t  *slots = mpt->m_active;
9112         mptsas_cmd_t    *cmd;
9113         int             slot;
9114 
9115         NDBG25(("mptsas_flush_hba"));
9116 
9117         /*
9118          * The I/O Controller should have already sent back
9119          * all commands via the scsi I/O reply frame.  Make
9120          * sure all commands have been flushed.
9121          * Account for TM request, which use the last SMID.
9122          */
9123         for (slot = 0; slot <= mpt->m_active->m_n_normal; slot++) {
9124                 if ((cmd = slots->m_slot[slot]) == NULL)
9125                         continue;
9126 
9127                 if (cmd->cmd_flags & CFLAG_CMDIOC) {
9128                         /*
9129                          * Need to make sure to tell everyone that might be
9130                          * waiting on this command that it's going to fail.  If
9131                          * we get here, this command will never timeout because
9132                          * the active command table is going to be re-allocated,
9133                          * so there will be nothing to check against a time out.
9134                          * Instead, mark the command as failed due to reset.
9135                          */
9136                         mptsas_set_pkt_reason(mpt, cmd, CMD_RESET,
9137                             STAT_BUS_RESET);
9138                         if ((cmd->cmd_flags &
9139                             (CFLAG_PASSTHRU | CFLAG_CONFIG | CFLAG_FW_DIAG))) {
9140                                 cmd->cmd_flags |= CFLAG_FINISHED;
9141                                 cv_broadcast(&mpt->m_passthru_cv);
9142                                 cv_broadcast(&mpt->m_config_cv);
9143                                 cv_broadcast(&mpt->m_fw_diag_cv);
9144                         }
9145                         continue;
9146                 }
9147 
9148                 NDBG25(("mptsas_flush_hba discovered non-NULL cmd in slot %d",
9149                     slot));
9150                 mptsas_dump_cmd(mpt, cmd);
9151 
9152                 mptsas_remove_cmd(mpt, cmd);
9153                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9154                 mptsas_doneq_add(mpt, cmd);
9155         }
9156 
9157         /*
9158          * Flush the waitq.
9159          */
9160         while ((cmd = mptsas_waitq_rm(mpt)) != NULL) {
9161                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9162                 if ((cmd->cmd_flags & CFLAG_PASSTHRU) ||
9163                     (cmd->cmd_flags & CFLAG_CONFIG) ||
9164                     (cmd->cmd_flags & CFLAG_FW_DIAG)) {
9165                         cmd->cmd_flags |= CFLAG_FINISHED;
9166                         cv_broadcast(&mpt->m_passthru_cv);
9167                         cv_broadcast(&mpt->m_config_cv);
9168                         cv_broadcast(&mpt->m_fw_diag_cv);
9169                 } else {
9170                         mptsas_doneq_add(mpt, cmd);
9171                 }
9172         }
9173 
9174         /*
9175          * Flush the tx_waitq
9176          */
9177         mutex_enter(&mpt->m_tx_waitq_mutex);
9178         while ((cmd = mptsas_tx_waitq_rm(mpt)) != NULL) {
9179                 mutex_exit(&mpt->m_tx_waitq_mutex);
9180                 mptsas_set_pkt_reason(mpt, cmd, CMD_RESET, STAT_BUS_RESET);
9181                 mptsas_doneq_add(mpt, cmd);
9182                 mutex_enter(&mpt->m_tx_waitq_mutex);
9183         }
9184         mutex_exit(&mpt->m_tx_waitq_mutex);
9185 
9186         /*
9187          * Drain the taskqs prior to reallocating resources.
9188          */
9189         mutex_exit(&mpt->m_mutex);
9190         ddi_taskq_wait(mpt->m_event_taskq);
9191         ddi_taskq_wait(mpt->m_dr_taskq);
9192         mutex_enter(&mpt->m_mutex);
9193 }
9194 
9195 /*
9196  * set pkt_reason and OR in pkt_statistics flag
9197  */
9198 static void
9199 mptsas_set_pkt_reason(mptsas_t *mpt, mptsas_cmd_t *cmd, uchar_t reason,
9200     uint_t stat)
9201 {
9202 #ifndef __lock_lint
9203         _NOTE(ARGUNUSED(mpt))
9204 #endif
9205 
9206         NDBG25(("mptsas_set_pkt_reason: cmd=0x%p reason=%x stat=%x",
9207             (void *)cmd, reason, stat));
9208 
9209         if (cmd) {
9210                 if (cmd->cmd_pkt->pkt_reason == CMD_CMPLT) {
9211                         cmd->cmd_pkt->pkt_reason = reason;
9212                 }
9213                 cmd->cmd_pkt->pkt_statistics |= stat;
9214         }
9215 }
9216 
9217 static void
9218 mptsas_start_watch_reset_delay()
9219 {
9220         NDBG22(("mptsas_start_watch_reset_delay"));
9221 
9222         mutex_enter(&mptsas_global_mutex);
9223         if (mptsas_reset_watch == NULL && mptsas_timeouts_enabled) {
9224                 mptsas_reset_watch = timeout(mptsas_watch_reset_delay, NULL,
9225                     drv_usectohz((clock_t)
9226                     MPTSAS_WATCH_RESET_DELAY_TICK * 1000));
9227                 ASSERT(mptsas_reset_watch != NULL);
9228         }
9229         mutex_exit(&mptsas_global_mutex);
9230 }
9231 
9232 static void
9233 mptsas_setup_bus_reset_delay(mptsas_t *mpt)
9234 {
9235         mptsas_target_t *ptgt = NULL;
9236 
9237         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9238 
9239         NDBG22(("mptsas_setup_bus_reset_delay"));
9240         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9241             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9242                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9243                 ptgt->m_reset_delay = mpt->m_scsi_reset_delay;
9244         }
9245 
9246         mptsas_start_watch_reset_delay();
9247 }
9248 
9249 /*
9250  * mptsas_watch_reset_delay(_subr) is invoked by timeout() and checks every
9251  * mpt instance for active reset delays
9252  */
9253 static void
9254 mptsas_watch_reset_delay(void *arg)
9255 {
9256 #ifndef __lock_lint
9257         _NOTE(ARGUNUSED(arg))
9258 #endif
9259 
9260         mptsas_t        *mpt;
9261         int             not_done = 0;
9262 
9263         NDBG22(("mptsas_watch_reset_delay"));
9264 
9265         mutex_enter(&mptsas_global_mutex);
9266         mptsas_reset_watch = 0;
9267         mutex_exit(&mptsas_global_mutex);
9268         rw_enter(&mptsas_global_rwlock, RW_READER);
9269         for (mpt = mptsas_head; mpt != NULL; mpt = mpt->m_next) {
9270                 if (mpt->m_tran == 0) {
9271                         continue;
9272                 }
9273                 mutex_enter(&mpt->m_mutex);
9274                 not_done += mptsas_watch_reset_delay_subr(mpt);
9275                 mutex_exit(&mpt->m_mutex);
9276         }
9277         rw_exit(&mptsas_global_rwlock);
9278 
9279         if (not_done) {
9280                 mptsas_start_watch_reset_delay();
9281         }
9282 }
9283 
9284 static int
9285 mptsas_watch_reset_delay_subr(mptsas_t *mpt)
9286 {
9287         int             done = 0;
9288         int             restart = 0;
9289         mptsas_target_t *ptgt = NULL;
9290 
9291         NDBG22(("mptsas_watch_reset_delay_subr: mpt=0x%p", (void *)mpt));
9292 
9293         ASSERT(mutex_owned(&mpt->m_mutex));
9294 
9295         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9296             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9297                 if (ptgt->m_reset_delay != 0) {
9298                         ptgt->m_reset_delay -=
9299                             MPTSAS_WATCH_RESET_DELAY_TICK;
9300                         if (ptgt->m_reset_delay <= 0) {
9301                                 ptgt->m_reset_delay = 0;
9302                                 mptsas_set_throttle(mpt, ptgt,
9303                                     MAX_THROTTLE);
9304                                 restart++;
9305                         } else {
9306                                 done = -1;
9307                         }
9308                 }
9309         }
9310 
9311         if (restart > 0) {
9312                 mptsas_restart_hba(mpt);
9313         }
9314         return (done);
9315 }
9316 
9317 #ifdef MPTSAS_TEST
9318 static void
9319 mptsas_test_reset(mptsas_t *mpt, int target)
9320 {
9321         mptsas_target_t    *ptgt = NULL;
9322 
9323         if (mptsas_rtest == target) {
9324                 if (mptsas_do_scsi_reset(mpt, target) == TRUE) {
9325                         mptsas_rtest = -1;
9326                 }
9327                 if (mptsas_rtest == -1) {
9328                         NDBG22(("mptsas_test_reset success"));
9329                 }
9330         }
9331 }
9332 #endif
9333 
9334 /*
9335  * abort handling:
9336  *
9337  * Notes:
9338  *      - if pkt is not NULL, abort just that command
9339  *      - if pkt is NULL, abort all outstanding commands for target
9340  */
9341 static int
9342 mptsas_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
9343 {
9344         mptsas_t                *mpt = ADDR2MPT(ap);
9345         int                     rval;
9346         mptsas_tgt_private_t    *tgt_private;
9347         int                     target, lun;
9348 
9349         tgt_private = (mptsas_tgt_private_t *)ap->a_hba_tran->
9350             tran_tgt_private;
9351         ASSERT(tgt_private != NULL);
9352         target = tgt_private->t_private->m_devhdl;
9353         lun = tgt_private->t_lun;
9354 
9355         NDBG23(("mptsas_scsi_abort: target=%d.%d", target, lun));
9356 
9357         mutex_enter(&mpt->m_mutex);
9358         rval = mptsas_do_scsi_abort(mpt, target, lun, pkt);
9359         mutex_exit(&mpt->m_mutex);
9360         return (rval);
9361 }
9362 
9363 static int
9364 mptsas_do_scsi_abort(mptsas_t *mpt, int target, int lun, struct scsi_pkt *pkt)
9365 {
9366         mptsas_cmd_t    *sp = NULL;
9367         mptsas_slots_t  *slots = mpt->m_active;
9368         int             rval = FALSE;
9369 
9370         ASSERT(mutex_owned(&mpt->m_mutex));
9371 
9372         /*
9373          * Abort the command pkt on the target/lun in ap.  If pkt is
9374          * NULL, abort all outstanding commands on that target/lun.
9375          * If you can abort them, return 1, else return 0.
9376          * Each packet that's aborted should be sent back to the target
9377          * driver through the callback routine, with pkt_reason set to
9378          * CMD_ABORTED.
9379          *
9380          * abort cmd pkt on HBA hardware; clean out of outstanding
9381          * command lists, etc.
9382          */
9383         if (pkt != NULL) {
9384                 /* abort the specified packet */
9385                 sp = PKT2CMD(pkt);
9386 
9387                 if (sp->cmd_queued) {
9388                         NDBG23(("mptsas_do_scsi_abort: queued sp=0x%p aborted",
9389                             (void *)sp));
9390                         mptsas_waitq_delete(mpt, sp);
9391                         mptsas_set_pkt_reason(mpt, sp, CMD_ABORTED,
9392                             STAT_ABORTED);
9393                         mptsas_doneq_add(mpt, sp);
9394                         rval = TRUE;
9395                         goto done;
9396                 }
9397 
9398                 /*
9399                  * Have mpt firmware abort this command
9400                  */
9401 
9402                 if (slots->m_slot[sp->cmd_slot] != NULL) {
9403                         rval = mptsas_ioc_task_management(mpt,
9404                             MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, target,
9405                             lun, NULL, 0, 0);
9406 
9407                         /*
9408                          * The transport layer expects only TRUE and FALSE.
9409                          * Therefore, if mptsas_ioc_task_management returns
9410                          * FAILED we will return FALSE.
9411                          */
9412                         if (rval == FAILED)
9413                                 rval = FALSE;
9414                         goto done;
9415                 }
9416         }
9417 
9418         /*
9419          * If pkt is NULL then abort task set
9420          */
9421         rval = mptsas_ioc_task_management(mpt,
9422             MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, target, lun, NULL, 0, 0);
9423 
9424         /*
9425          * The transport layer expects only TRUE and FALSE.
9426          * Therefore, if mptsas_ioc_task_management returns
9427          * FAILED we will return FALSE.
9428          */
9429         if (rval == FAILED)
9430                 rval = FALSE;
9431 
9432 #ifdef MPTSAS_TEST
9433         if (rval && mptsas_test_stop) {
9434                 debug_enter("mptsas_do_scsi_abort");
9435         }
9436 #endif
9437 
9438 done:
9439         mptsas_doneq_empty(mpt);
9440         return (rval);
9441 }
9442 
9443 /*
9444  * capability handling:
9445  * (*tran_getcap).  Get the capability named, and return its value.
9446  */
9447 static int
9448 mptsas_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly)
9449 {
9450         mptsas_t        *mpt = ADDR2MPT(ap);
9451         int             ckey;
9452         int             rval = FALSE;
9453 
9454         NDBG24(("mptsas_scsi_getcap: target=%d, cap=%s tgtonly=%x",
9455             ap->a_target, cap, tgtonly));
9456 
9457         mutex_enter(&mpt->m_mutex);
9458 
9459         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9460                 mutex_exit(&mpt->m_mutex);
9461                 return (UNDEFINED);
9462         }
9463 
9464         switch (ckey) {
9465         case SCSI_CAP_DMA_MAX:
9466                 rval = (int)mpt->m_msg_dma_attr.dma_attr_maxxfer;
9467                 break;
9468         case SCSI_CAP_ARQ:
9469                 rval = TRUE;
9470                 break;
9471         case SCSI_CAP_MSG_OUT:
9472         case SCSI_CAP_PARITY:
9473         case SCSI_CAP_UNTAGGED_QING:
9474                 rval = TRUE;
9475                 break;
9476         case SCSI_CAP_TAGGED_QING:
9477                 rval = TRUE;
9478                 break;
9479         case SCSI_CAP_RESET_NOTIFICATION:
9480                 rval = TRUE;
9481                 break;
9482         case SCSI_CAP_LINKED_CMDS:
9483                 rval = FALSE;
9484                 break;
9485         case SCSI_CAP_QFULL_RETRIES:
9486                 rval = ((mptsas_tgt_private_t *)(ap->a_hba_tran->
9487                     tran_tgt_private))->t_private->m_qfull_retries;
9488                 break;
9489         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9490                 rval = drv_hztousec(((mptsas_tgt_private_t *)
9491                     (ap->a_hba_tran->tran_tgt_private))->
9492                     t_private->m_qfull_retry_interval) / 1000;
9493                 break;
9494         case SCSI_CAP_CDB_LEN:
9495                 rval = CDB_GROUP4;
9496                 break;
9497         case SCSI_CAP_INTERCONNECT_TYPE:
9498                 rval = INTERCONNECT_SAS;
9499                 break;
9500         case SCSI_CAP_TRAN_LAYER_RETRIES:
9501                 if (mpt->m_ioc_capabilities &
9502                     MPI2_IOCFACTS_CAPABILITY_TLR)
9503                         rval = TRUE;
9504                 else
9505                         rval = FALSE;
9506                 break;
9507         default:
9508                 rval = UNDEFINED;
9509                 break;
9510         }
9511 
9512         NDBG24(("mptsas_scsi_getcap: %s, rval=%x", cap, rval));
9513 
9514         mutex_exit(&mpt->m_mutex);
9515         return (rval);
9516 }
9517 
9518 /*
9519  * (*tran_setcap).  Set the capability named to the value given.
9520  */
9521 static int
9522 mptsas_scsi_setcap(struct scsi_address *ap, char *cap, int value, int tgtonly)
9523 {
9524         mptsas_t        *mpt = ADDR2MPT(ap);
9525         int             ckey;
9526         int             rval = FALSE;
9527 
9528         NDBG24(("mptsas_scsi_setcap: target=%d, cap=%s value=%x tgtonly=%x",
9529             ap->a_target, cap, value, tgtonly));
9530 
9531         if (!tgtonly) {
9532                 return (rval);
9533         }
9534 
9535         mutex_enter(&mpt->m_mutex);
9536 
9537         if ((mptsas_scsi_capchk(cap, tgtonly, &ckey)) != TRUE) {
9538                 mutex_exit(&mpt->m_mutex);
9539                 return (UNDEFINED);
9540         }
9541 
9542         switch (ckey) {
9543         case SCSI_CAP_DMA_MAX:
9544         case SCSI_CAP_MSG_OUT:
9545         case SCSI_CAP_PARITY:
9546         case SCSI_CAP_INITIATOR_ID:
9547         case SCSI_CAP_LINKED_CMDS:
9548         case SCSI_CAP_UNTAGGED_QING:
9549         case SCSI_CAP_RESET_NOTIFICATION:
9550                 /*
9551                  * None of these are settable via
9552                  * the capability interface.
9553                  */
9554                 break;
9555         case SCSI_CAP_ARQ:
9556                 /*
9557                  * We cannot turn off arq so return false if asked to
9558                  */
9559                 if (value) {
9560                         rval = TRUE;
9561                 } else {
9562                         rval = FALSE;
9563                 }
9564                 break;
9565         case SCSI_CAP_TAGGED_QING:
9566                 mptsas_set_throttle(mpt, ((mptsas_tgt_private_t *)
9567                     (ap->a_hba_tran->tran_tgt_private))->t_private,
9568                     MAX_THROTTLE);
9569                 rval = TRUE;
9570                 break;
9571         case SCSI_CAP_QFULL_RETRIES:
9572                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9573                     t_private->m_qfull_retries = (uchar_t)value;
9574                 rval = TRUE;
9575                 break;
9576         case SCSI_CAP_QFULL_RETRY_INTERVAL:
9577                 ((mptsas_tgt_private_t *)(ap->a_hba_tran->tran_tgt_private))->
9578                     t_private->m_qfull_retry_interval =
9579                     drv_usectohz(value * 1000);
9580                 rval = TRUE;
9581                 break;
9582         default:
9583                 rval = UNDEFINED;
9584                 break;
9585         }
9586         mutex_exit(&mpt->m_mutex);
9587         return (rval);
9588 }
9589 
9590 /*
9591  * Utility routine for mptsas_ifsetcap/ifgetcap
9592  */
9593 /*ARGSUSED*/
9594 static int
9595 mptsas_scsi_capchk(char *cap, int tgtonly, int *cidxp)
9596 {
9597         NDBG24(("mptsas_scsi_capchk: cap=%s", cap));
9598 
9599         if (!cap)
9600                 return (FALSE);
9601 
9602         *cidxp = scsi_hba_lookup_capstr(cap);
9603         return (TRUE);
9604 }
9605 
9606 static int
9607 mptsas_alloc_active_slots(mptsas_t *mpt, int flag)
9608 {
9609         mptsas_slots_t  *old_active = mpt->m_active;
9610         mptsas_slots_t  *new_active;
9611         size_t          size;
9612 
9613         /*
9614          * if there are active commands, then we cannot
9615          * change size of active slots array.
9616          */
9617         ASSERT(mpt->m_ncmds == 0);
9618 
9619         size = MPTSAS_SLOTS_SIZE(mpt);
9620         new_active = kmem_zalloc(size, flag);
9621         if (new_active == NULL) {
9622                 NDBG1(("new active alloc failed"));
9623                 return (-1);
9624         }
9625         /*
9626          * Since SMID 0 is reserved and the TM slot is reserved, the
9627          * number of slots that can be used at any one time is
9628          * m_max_requests - 2.
9629          */
9630         new_active->m_n_normal = (mpt->m_max_requests - 2);
9631         new_active->m_size = size;
9632         new_active->m_rotor = 1;
9633         if (old_active)
9634                 mptsas_free_active_slots(mpt);
9635         mpt->m_active = new_active;
9636 
9637         return (0);
9638 }
9639 
9640 static void
9641 mptsas_free_active_slots(mptsas_t *mpt)
9642 {
9643         mptsas_slots_t  *active = mpt->m_active;
9644         size_t          size;
9645 
9646         if (active == NULL)
9647                 return;
9648         size = active->m_size;
9649         kmem_free(active, size);
9650         mpt->m_active = NULL;
9651 }
9652 
9653 /*
9654  * Error logging, printing, and debug print routines.
9655  */
9656 static char *mptsas_label = "mpt_sas";
9657 
9658 /*PRINTFLIKE3*/
9659 void
9660 mptsas_log(mptsas_t *mpt, int level, char *fmt, ...)
9661 {
9662         dev_info_t      *dev;
9663         va_list         ap;
9664 
9665         if (mpt) {
9666                 dev = mpt->m_dip;
9667         } else {
9668                 dev = 0;
9669         }
9670 
9671         mutex_enter(&mptsas_log_mutex);
9672 
9673         va_start(ap, fmt);
9674         (void) vsprintf(mptsas_log_buf, fmt, ap);
9675         va_end(ap);
9676 
9677         if (level == CE_CONT) {
9678                 scsi_log(dev, mptsas_label, level, "%s\n", mptsas_log_buf);
9679         } else {
9680                 scsi_log(dev, mptsas_label, level, "%s", mptsas_log_buf);
9681         }
9682 
9683         mutex_exit(&mptsas_log_mutex);
9684 }
9685 
9686 #ifdef MPTSAS_DEBUG
9687 /*
9688  * Use a circular buffer to log messages to private memory.
9689  * Increment idx atomically to minimize risk to miss lines.
9690  * It's fast and does not hold up the proceedings too much.
9691  */
9692 static const size_t mptsas_dbglog_linecnt = MPTSAS_DBGLOG_LINECNT;
9693 static const size_t mptsas_dbglog_linelen = MPTSAS_DBGLOG_LINELEN;
9694 static char mptsas_dbglog_bufs[MPTSAS_DBGLOG_LINECNT][MPTSAS_DBGLOG_LINELEN];
9695 static uint32_t mptsas_dbglog_idx = 0;
9696 
9697 /*PRINTFLIKE1*/
9698 void
9699 mptsas_debug_log(char *fmt, ...)
9700 {
9701         va_list         ap;
9702         uint32_t        idx;
9703 
9704         idx = atomic_inc_32_nv(&mptsas_dbglog_idx) &
9705             (mptsas_dbglog_linecnt - 1);
9706 
9707         va_start(ap, fmt);
9708         (void) vsnprintf(mptsas_dbglog_bufs[idx],
9709             mptsas_dbglog_linelen, fmt, ap);
9710         va_end(ap);
9711 }
9712 
9713 /*PRINTFLIKE1*/
9714 void
9715 mptsas_printf(char *fmt, ...)
9716 {
9717         dev_info_t      *dev = 0;
9718         va_list         ap;
9719 
9720         mutex_enter(&mptsas_log_mutex);
9721 
9722         va_start(ap, fmt);
9723         (void) vsprintf(mptsas_log_buf, fmt, ap);
9724         va_end(ap);
9725 
9726 #ifdef PROM_PRINTF
9727         prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9728 #else
9729         scsi_log(dev, mptsas_label, CE_CONT, "!%s\n", mptsas_log_buf);
9730 #endif
9731         mutex_exit(&mptsas_log_mutex);
9732 }
9733 #endif
9734 
9735 /*
9736  * timeout handling
9737  */
9738 static void
9739 mptsas_watch(void *arg)
9740 {
9741 #ifndef __lock_lint
9742         _NOTE(ARGUNUSED(arg))
9743 #endif
9744 
9745         mptsas_t        *mpt;
9746         uint32_t        doorbell;
9747 
9748         NDBG30(("mptsas_watch"));
9749 
9750         rw_enter(&mptsas_global_rwlock, RW_READER);
9751         for (mpt = mptsas_head; mpt != (mptsas_t *)NULL; mpt = mpt->m_next) {
9752 
9753                 mutex_enter(&mpt->m_mutex);
9754 
9755                 /* Skip device if not powered on */
9756                 if (mpt->m_options & MPTSAS_OPT_PM) {
9757                         if (mpt->m_power_level == PM_LEVEL_D0) {
9758                                 (void) pm_busy_component(mpt->m_dip, 0);
9759                                 mpt->m_busy = 1;
9760                         } else {
9761                                 mutex_exit(&mpt->m_mutex);
9762                                 continue;
9763                         }
9764                 }
9765 
9766                 /*
9767                  * Check if controller is in a FAULT state. If so, reset it.
9768                  */
9769                 doorbell = ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell);
9770                 if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
9771                         doorbell &= MPI2_DOORBELL_DATA_MASK;
9772                         mptsas_log(mpt, CE_WARN, "MPT Firmware Fault, "
9773                             "code: %04x", doorbell);
9774                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
9775                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
9776                                 mptsas_log(mpt, CE_WARN, "Reset failed"
9777                                     "after fault was detected");
9778                         }
9779                 }
9780 
9781                 /*
9782                  * For now, always call mptsas_watchsubr.
9783                  */
9784                 mptsas_watchsubr(mpt);
9785 
9786                 if (mpt->m_options & MPTSAS_OPT_PM) {
9787                         mpt->m_busy = 0;
9788                         (void) pm_idle_component(mpt->m_dip, 0);
9789                 }
9790 
9791                 mutex_exit(&mpt->m_mutex);
9792         }
9793         rw_exit(&mptsas_global_rwlock);
9794 
9795         mutex_enter(&mptsas_global_mutex);
9796         if (mptsas_timeouts_enabled)
9797                 mptsas_timeout_id = timeout(mptsas_watch, NULL, mptsas_tick);
9798         mutex_exit(&mptsas_global_mutex);
9799 }
9800 
9801 static void
9802 mptsas_watchsubr(mptsas_t *mpt)
9803 {
9804         int             i;
9805         mptsas_cmd_t    *cmd;
9806         mptsas_target_t *ptgt = NULL;
9807         hrtime_t        timestamp = gethrtime();
9808 
9809         ASSERT(MUTEX_HELD(&mpt->m_mutex));
9810 
9811         NDBG30(("mptsas_watchsubr: mpt=0x%p", (void *)mpt));
9812 
9813 #ifdef MPTSAS_TEST
9814         if (mptsas_enable_untagged) {
9815                 mptsas_test_untagged++;
9816         }
9817 #endif
9818 
9819         /*
9820          * Check for commands stuck in active slot
9821          * Account for TM requests, which use the last SMID.
9822          */
9823         for (i = 0; i <= mpt->m_active->m_n_normal; i++) {
9824                 if ((cmd = mpt->m_active->m_slot[i]) != NULL) {
9825                         if (cmd->cmd_active_expiration <= timestamp) {
9826                                 if ((cmd->cmd_flags & CFLAG_CMDIOC) == 0) {
9827                                         /*
9828                                          * There seems to be a command stuck
9829                                          * in the active slot.  Drain throttle.
9830                                          */
9831                                         mptsas_set_throttle(mpt,
9832                                             cmd->cmd_tgt_addr,
9833                                             DRAIN_THROTTLE);
9834                                 } else if (cmd->cmd_flags &
9835                                     (CFLAG_PASSTHRU | CFLAG_CONFIG |
9836                                     CFLAG_FW_DIAG)) {
9837                                         /*
9838                                          * passthrough command timeout
9839                                          */
9840                                         cmd->cmd_flags |= (CFLAG_FINISHED |
9841                                             CFLAG_TIMEOUT);
9842                                         cv_broadcast(&mpt->m_passthru_cv);
9843                                         cv_broadcast(&mpt->m_config_cv);
9844                                         cv_broadcast(&mpt->m_fw_diag_cv);
9845                                 }
9846                         }
9847                 }
9848         }
9849 
9850         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9851             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9852                 /*
9853                  * If we were draining due to a qfull condition,
9854                  * go back to full throttle.
9855                  */
9856                 if ((ptgt->m_t_throttle < MAX_THROTTLE) &&
9857                     (ptgt->m_t_throttle > HOLD_THROTTLE) &&
9858                     (ptgt->m_t_ncmds < ptgt->m_t_throttle)) {
9859                         mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9860                         mptsas_restart_hba(mpt);
9861                 }
9862 
9863                 cmd = TAILQ_LAST(&ptgt->m_active_cmdq, mptsas_active_cmdq);
9864                 if (cmd == NULL)
9865                         continue;
9866 
9867                 if (cmd->cmd_active_expiration <= timestamp) {
9868                         /*
9869                          * Earliest command timeout expired. Drain throttle.
9870                          */
9871                         mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9872 
9873                         /*
9874                          * Check for remaining commands.
9875                          */
9876                         cmd = TAILQ_FIRST(&ptgt->m_active_cmdq);
9877                         if (cmd->cmd_active_expiration > timestamp) {
9878                                 /*
9879                                  * Wait for remaining commands to complete or
9880                                  * time out.
9881                                  */
9882                                 NDBG23(("command timed out, pending drain"));
9883                                 continue;
9884                         }
9885 
9886                         /*
9887                          * All command timeouts expired.
9888                          */
9889                         mptsas_log(mpt, CE_NOTE, "Timeout of %d seconds "
9890                             "expired with %d commands on target %d lun %d.",
9891                             cmd->cmd_pkt->pkt_time, ptgt->m_t_ncmds,
9892                             ptgt->m_devhdl, Lun(cmd));
9893 
9894                         mptsas_cmd_timeout(mpt, ptgt);
9895                 } else if (cmd->cmd_active_expiration <=
9896                     timestamp + (hrtime_t)mptsas_scsi_watchdog_tick * NANOSEC) {
9897                         NDBG23(("pending timeout"));
9898                         mptsas_set_throttle(mpt, ptgt, DRAIN_THROTTLE);
9899                 }
9900         }
9901 }
9902 
9903 /*
9904  * timeout recovery
9905  */
9906 static void
9907 mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt)
9908 {
9909         uint16_t        devhdl;
9910         uint64_t        sas_wwn;
9911         uint8_t         phy;
9912         char            wwn_str[MPTSAS_WWN_STRLEN];
9913 
9914         devhdl = ptgt->m_devhdl;
9915         sas_wwn = ptgt->m_addr.mta_wwn;
9916         phy = ptgt->m_phynum;
9917         if (sas_wwn == 0) {
9918                 (void) sprintf(wwn_str, "p%x", phy);
9919         } else {
9920                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
9921         }
9922 
9923         NDBG29(("mptsas_cmd_timeout: target=%d", devhdl));
9924         mptsas_log(mpt, CE_WARN, "Disconnected command timeout for "
9925             "target %d %s, enclosure %u", devhdl, wwn_str,
9926             ptgt->m_enclosure);
9927 
9928         /*
9929          * Abort all outstanding commands on the device.
9930          */
9931         NDBG29(("mptsas_cmd_timeout: device reset"));
9932         if (mptsas_do_scsi_reset(mpt, devhdl) != TRUE) {
9933                 mptsas_log(mpt, CE_WARN, "Target %d reset for command timeout "
9934                     "recovery failed!", devhdl);
9935         }
9936 }
9937 
9938 /*
9939  * Device / Hotplug control
9940  */
9941 static int
9942 mptsas_scsi_quiesce(dev_info_t *dip)
9943 {
9944         mptsas_t        *mpt;
9945         scsi_hba_tran_t *tran;
9946 
9947         tran = ddi_get_driver_private(dip);
9948         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9949                 return (-1);
9950 
9951         return (mptsas_quiesce_bus(mpt));
9952 }
9953 
9954 static int
9955 mptsas_scsi_unquiesce(dev_info_t *dip)
9956 {
9957         mptsas_t                *mpt;
9958         scsi_hba_tran_t *tran;
9959 
9960         tran = ddi_get_driver_private(dip);
9961         if (tran == NULL || (mpt = TRAN2MPT(tran)) == NULL)
9962                 return (-1);
9963 
9964         return (mptsas_unquiesce_bus(mpt));
9965 }
9966 
9967 static int
9968 mptsas_quiesce_bus(mptsas_t *mpt)
9969 {
9970         mptsas_target_t *ptgt = NULL;
9971 
9972         NDBG28(("mptsas_quiesce_bus"));
9973         mutex_enter(&mpt->m_mutex);
9974 
9975         /* Set all the throttles to zero */
9976         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9977             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9978                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
9979         }
9980 
9981         /* If there are any outstanding commands in the queue */
9982         if (mpt->m_ncmds) {
9983                 mpt->m_softstate |= MPTSAS_SS_DRAINING;
9984                 mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
9985                     mpt, (MPTSAS_QUIESCE_TIMEOUT * drv_usectohz(1000000)));
9986                 if (cv_wait_sig(&mpt->m_cv, &mpt->m_mutex) == 0) {
9987                         /*
9988                          * Quiesce has been interrupted
9989                          */
9990                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
9991                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
9992                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
9993                                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
9994                         }
9995                         mptsas_restart_hba(mpt);
9996                         if (mpt->m_quiesce_timeid != 0) {
9997                                 timeout_id_t tid = mpt->m_quiesce_timeid;
9998                                 mpt->m_quiesce_timeid = 0;
9999                                 mutex_exit(&mpt->m_mutex);
10000                                 (void) untimeout(tid);
10001                                 return (-1);
10002                         }
10003                         mutex_exit(&mpt->m_mutex);
10004                         return (-1);
10005                 } else {
10006                         /* Bus has been quiesced */
10007                         ASSERT(mpt->m_quiesce_timeid == 0);
10008                         mpt->m_softstate &= ~MPTSAS_SS_DRAINING;
10009                         mpt->m_softstate |= MPTSAS_SS_QUIESCED;
10010                         mutex_exit(&mpt->m_mutex);
10011                         return (0);
10012                 }
10013         }
10014         /* Bus was not busy - QUIESCED */
10015         mutex_exit(&mpt->m_mutex);
10016 
10017         return (0);
10018 }
10019 
10020 static int
10021 mptsas_unquiesce_bus(mptsas_t *mpt)
10022 {
10023         mptsas_target_t *ptgt = NULL;
10024 
10025         NDBG28(("mptsas_unquiesce_bus"));
10026         mutex_enter(&mpt->m_mutex);
10027         mpt->m_softstate &= ~MPTSAS_SS_QUIESCED;
10028         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10029             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10030                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
10031         }
10032         mptsas_restart_hba(mpt);
10033         mutex_exit(&mpt->m_mutex);
10034         return (0);
10035 }
10036 
10037 static void
10038 mptsas_ncmds_checkdrain(void *arg)
10039 {
10040         mptsas_t        *mpt = arg;
10041         mptsas_target_t *ptgt = NULL;
10042 
10043         mutex_enter(&mpt->m_mutex);
10044         if (mpt->m_softstate & MPTSAS_SS_DRAINING) {
10045                 mpt->m_quiesce_timeid = 0;
10046                 if (mpt->m_ncmds == 0) {
10047                         /* Command queue has been drained */
10048                         cv_signal(&mpt->m_cv);
10049                 } else {
10050                         /*
10051                          * The throttle may have been reset because
10052                          * of a SCSI bus reset
10053                          */
10054                         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
10055                             ptgt = refhash_next(mpt->m_targets, ptgt)) {
10056                                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
10057                         }
10058 
10059                         mpt->m_quiesce_timeid = timeout(mptsas_ncmds_checkdrain,
10060                             mpt, (MPTSAS_QUIESCE_TIMEOUT *
10061                             drv_usectohz(1000000)));
10062                 }
10063         }
10064         mutex_exit(&mpt->m_mutex);
10065 }
10066 
10067 /*ARGSUSED*/
10068 static void
10069 mptsas_dump_cmd(mptsas_t *mpt, mptsas_cmd_t *cmd)
10070 {
10071         int     i;
10072         uint8_t *cp = (uchar_t *)cmd->cmd_pkt->pkt_cdbp;
10073         char    buf[128];
10074 
10075         buf[0] = '\0';
10076         NDBG25(("?Cmd (0x%p) dump for Target %d Lun %d:\n", (void *)cmd,
10077             Tgt(cmd), Lun(cmd)));
10078         (void) sprintf(&buf[0], "\tcdb=[");
10079         for (i = 0; i < (int)cmd->cmd_cdblen; i++) {
10080                 (void) sprintf(&buf[strlen(buf)], " 0x%x", *cp++);
10081         }
10082         (void) sprintf(&buf[strlen(buf)], " ]");
10083         NDBG25(("?%s\n", buf));
10084         NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
10085             cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
10086             cmd->cmd_pkt->pkt_state));
10087         NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
10088             *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
10089 }
10090 
10091 static void
10092 mptsas_passthru_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
10093     pMpi2SGESimple64_t sgep)
10094 {
10095         uint32_t                sge_flags;
10096         uint32_t                data_size, dataout_size;
10097         ddi_dma_cookie_t        data_cookie;
10098         ddi_dma_cookie_t        dataout_cookie;
10099 
10100         data_size = pt->data_size;
10101         dataout_size = pt->dataout_size;
10102         data_cookie = pt->data_cookie;
10103         dataout_cookie = pt->dataout_cookie;
10104 
10105         if (dataout_size) {
10106                 sge_flags = dataout_size |
10107                     ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10108                     MPI2_SGE_FLAGS_END_OF_BUFFER |
10109                     MPI2_SGE_FLAGS_HOST_TO_IOC |
10110                     MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10111                     MPI2_SGE_FLAGS_SHIFT);
10112                 ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
10113                 ddi_put32(acc_hdl, &sgep->Address.Low,
10114                     (uint32_t)(dataout_cookie.dmac_laddress &
10115                     0xffffffffull));
10116                 ddi_put32(acc_hdl, &sgep->Address.High,
10117                     (uint32_t)(dataout_cookie.dmac_laddress
10118                     >> 32));
10119                 sgep++;
10120         }
10121         sge_flags = data_size;
10122         sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
10123             MPI2_SGE_FLAGS_LAST_ELEMENT |
10124             MPI2_SGE_FLAGS_END_OF_BUFFER |
10125             MPI2_SGE_FLAGS_END_OF_LIST |
10126             MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
10127             MPI2_SGE_FLAGS_SHIFT);
10128         if (pt->direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10129                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
10130                     MPI2_SGE_FLAGS_SHIFT);
10131         } else {
10132                 sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
10133                     MPI2_SGE_FLAGS_SHIFT);
10134         }
10135         ddi_put32(acc_hdl, &sgep->FlagsLength,
10136             sge_flags);
10137         ddi_put32(acc_hdl, &sgep->Address.Low,
10138             (uint32_t)(data_cookie.dmac_laddress &
10139             0xffffffffull));
10140         ddi_put32(acc_hdl, &sgep->Address.High,
10141             (uint32_t)(data_cookie.dmac_laddress >> 32));
10142 }
10143 
10144 static void
10145 mptsas_passthru_ieee_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
10146     pMpi2IeeeSgeSimple64_t ieeesgep)
10147 {
10148         uint8_t                 sge_flags;
10149         uint32_t                data_size, dataout_size;
10150         ddi_dma_cookie_t        data_cookie;
10151         ddi_dma_cookie_t        dataout_cookie;
10152 
10153         data_size = pt->data_size;
10154         dataout_size = pt->dataout_size;
10155         data_cookie = pt->data_cookie;
10156         dataout_cookie = pt->dataout_cookie;
10157 
10158         sge_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
10159             MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
10160         if (dataout_size) {
10161                 ddi_put32(acc_hdl, &ieeesgep->Length, dataout_size);
10162                 ddi_put32(acc_hdl, &ieeesgep->Address.Low,
10163                     (uint32_t)(dataout_cookie.dmac_laddress &
10164                     0xffffffffull));
10165                 ddi_put32(acc_hdl, &ieeesgep->Address.High,
10166                     (uint32_t)(dataout_cookie.dmac_laddress >> 32));
10167                 ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
10168                 ieeesgep++;
10169         }
10170         sge_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
10171         ddi_put32(acc_hdl, &ieeesgep->Length, data_size);
10172         ddi_put32(acc_hdl, &ieeesgep->Address.Low,
10173             (uint32_t)(data_cookie.dmac_laddress & 0xffffffffull));
10174         ddi_put32(acc_hdl, &ieeesgep->Address.High,
10175             (uint32_t)(data_cookie.dmac_laddress >> 32));
10176         ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
10177 }
10178 
10179 static void
10180 mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
10181 {
10182         caddr_t                 memp;
10183         pMPI2RequestHeader_t    request_hdrp;
10184         struct scsi_pkt         *pkt = cmd->cmd_pkt;
10185         mptsas_pt_request_t     *pt = pkt->pkt_ha_private;
10186         uint32_t                request_size;
10187         uint32_t                request_desc_low, request_desc_high = 0;
10188         uint32_t                i, sense_bufp;
10189         uint8_t                 desc_type;
10190         uint8_t                 *request, function;
10191         ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
10192         ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
10193 
10194         desc_type = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
10195 
10196         request = pt->request;
10197         request_size = pt->request_size;
10198 
10199         /*
10200          * Store the passthrough message in memory location
10201          * corresponding to our slot number
10202          */
10203         memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
10204         request_hdrp = (pMPI2RequestHeader_t)memp;
10205         bzero(memp, mpt->m_req_frame_size);
10206 
10207         for (i = 0; i < request_size; i++) {
10208                 bcopy(request + i, memp + i, 1);
10209         }
10210 
10211         NDBG15(("mptsas_start_passthru: Func 0x%x, MsgFlags 0x%x, "
10212             "size=%d, in %d, out %d", request_hdrp->Function,
10213             request_hdrp->MsgFlags, request_size,
10214             pt->data_size, pt->dataout_size));
10215 
10216         /*
10217          * Add an SGE, even if the length is zero.
10218          */
10219         if (mpt->m_MPI25 && pt->simple == 0) {
10220                 mptsas_passthru_ieee_sge(acc_hdl, pt,
10221                     (pMpi2IeeeSgeSimple64_t)
10222                     ((uint8_t *)request_hdrp + pt->sgl_offset));
10223         } else {
10224                 mptsas_passthru_sge(acc_hdl, pt,
10225                     (pMpi2SGESimple64_t)
10226                     ((uint8_t *)request_hdrp + pt->sgl_offset));
10227         }
10228 
10229         function = request_hdrp->Function;
10230         if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10231             (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10232                 pMpi2SCSIIORequest_t    scsi_io_req;
10233 
10234                 NDBG15(("mptsas_start_passthru: Is SCSI IO Req"));
10235                 scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
10236                 /*
10237                  * Put SGE for data and data_out buffer at the end of
10238                  * scsi_io_request message header.(64 bytes in total)
10239                  * Following above SGEs, the residual space will be
10240                  * used by sense data.
10241                  */
10242                 ddi_put8(acc_hdl,
10243                     &scsi_io_req->SenseBufferLength,
10244                     (uint8_t)(request_size - 64));
10245 
10246                 sense_bufp = mpt->m_req_frame_dma_addr +
10247                     (mpt->m_req_frame_size * cmd->cmd_slot);
10248                 sense_bufp += 64;
10249                 ddi_put32(acc_hdl,
10250                     &scsi_io_req->SenseBufferLowAddress, sense_bufp);
10251 
10252                 /*
10253                  * Set SGLOffset0 value
10254                  */
10255                 ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
10256                     offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
10257 
10258                 /*
10259                  * Setup descriptor info.  RAID passthrough must use the
10260                  * default request descriptor which is already set, so if this
10261                  * is a SCSI IO request, change the descriptor to SCSI IO.
10262                  */
10263                 if (function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
10264                         desc_type = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
10265                         request_desc_high = (ddi_get16(acc_hdl,
10266                             &scsi_io_req->DevHandle) << 16);
10267                 }
10268         }
10269 
10270         /*
10271          * We must wait till the message has been completed before
10272          * beginning the next message so we wait for this one to
10273          * finish.
10274          */
10275         (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
10276         request_desc_low = (cmd->cmd_slot << 16) + desc_type;
10277         cmd->cmd_rfm = NULL;
10278         MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
10279         if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
10280             (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
10281                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
10282         }
10283 }
10284 
10285 typedef void (mptsas_pre_f)(mptsas_t *, mptsas_pt_request_t *);
10286 static mptsas_pre_f     mpi_pre_ioc_facts;
10287 static mptsas_pre_f     mpi_pre_port_facts;
10288 static mptsas_pre_f     mpi_pre_fw_download;
10289 static mptsas_pre_f     mpi_pre_fw_25_download;
10290 static mptsas_pre_f     mpi_pre_fw_upload;
10291 static mptsas_pre_f     mpi_pre_fw_25_upload;
10292 static mptsas_pre_f     mpi_pre_sata_passthrough;
10293 static mptsas_pre_f     mpi_pre_smp_passthrough;
10294 static mptsas_pre_f     mpi_pre_config;
10295 static mptsas_pre_f     mpi_pre_sas_io_unit_control;
10296 static mptsas_pre_f     mpi_pre_scsi_io_req;
10297 
10298 /*
10299  * Prepare the pt for a SAS2 FW_DOWNLOAD request.
10300  */
10301 static void
10302 mpi_pre_fw_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
10303 {
10304         pMpi2FWDownloadTCSGE_t tcsge;
10305         pMpi2FWDownloadRequest req;
10306 
10307         /*
10308          * If SAS3, call separate function.
10309          */
10310         if (mpt->m_MPI25) {
10311                 mpi_pre_fw_25_download(mpt, pt);
10312                 return;
10313         }
10314 
10315         /*
10316          * User requests should come in with the Transaction
10317          * context element where the SGL will go. Putting the
10318          * SGL after that seems to work, but don't really know
10319          * why. Other drivers tend to create an extra SGL and
10320          * refer to the TCE through that.
10321          */
10322         req = (pMpi2FWDownloadRequest)pt->request;
10323         tcsge = (pMpi2FWDownloadTCSGE_t)&req->SGL;
10324         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10325             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10326                 mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
10327         }
10328 
10329         pt->sgl_offset = offsetof(MPI2_FW_DOWNLOAD_REQUEST, SGL) +
10330             sizeof (*tcsge);
10331         if (pt->request_size != pt->sgl_offset)
10332                 NDBG15(("mpi_pre_fw_download(): Incorrect req size, "
10333                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10334                     (int)pt->request_size, (int)pt->sgl_offset,
10335                     (int)pt->dataout_size));
10336         if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
10337                 NDBG15(("mpi_pre_fw_download(): Incorrect rep size, "
10338                     "0x%x, should be 0x%x", pt->data_size,
10339                     (int)sizeof (MPI2_FW_DOWNLOAD_REPLY)));
10340 }
10341 
10342 /*
10343  * Prepare the pt for a SAS3 FW_DOWNLOAD request.
10344  */
10345 static void
10346 mpi_pre_fw_25_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
10347 {
10348         pMpi2FWDownloadTCSGE_t tcsge;
10349         pMpi2FWDownloadRequest req2;
10350         pMpi25FWDownloadRequest req25;
10351 
10352         /*
10353          * User requests should come in with the Transaction
10354          * context element where the SGL will go. The new firmware
10355          * Doesn't use TCE and has space in the main request for
10356          * this information. So move to the right place.
10357          */
10358         req2 = (pMpi2FWDownloadRequest)pt->request;
10359         req25 = (pMpi25FWDownloadRequest)pt->request;
10360         tcsge = (pMpi2FWDownloadTCSGE_t)&req2->SGL;
10361         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10362             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10363                 mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
10364         }
10365         req25->ImageOffset = tcsge->ImageOffset;
10366         req25->ImageSize = tcsge->ImageSize;
10367 
10368         pt->sgl_offset = offsetof(MPI25_FW_DOWNLOAD_REQUEST, SGL);
10369         if (pt->request_size != pt->sgl_offset)
10370                 NDBG15(("mpi_pre_fw_25_download(): Incorrect req size, "
10371                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10372                     pt->request_size, pt->sgl_offset,
10373                     pt->dataout_size));
10374         if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
10375                 NDBG15(("mpi_pre_fw_25_download(): Incorrect rep size, "
10376                     "0x%x, should be 0x%x", pt->data_size,
10377                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10378 }
10379 
10380 /*
10381  * Prepare the pt for a SAS2 FW_UPLOAD request.
10382  */
10383 static void
10384 mpi_pre_fw_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
10385 {
10386         pMpi2FWUploadTCSGE_t tcsge;
10387         pMpi2FWUploadRequest_t req;
10388 
10389         /*
10390          * If SAS3, call separate function.
10391          */
10392         if (mpt->m_MPI25) {
10393                 mpi_pre_fw_25_upload(mpt, pt);
10394                 return;
10395         }
10396 
10397         /*
10398          * User requests should come in with the Transaction
10399          * context element where the SGL will go. Putting the
10400          * SGL after that seems to work, but don't really know
10401          * why. Other drivers tend to create an extra SGL and
10402          * refer to the TCE through that.
10403          */
10404         req = (pMpi2FWUploadRequest_t)pt->request;
10405         tcsge = (pMpi2FWUploadTCSGE_t)&req->SGL;
10406         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10407             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10408                 mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
10409         }
10410 
10411         pt->sgl_offset = offsetof(MPI2_FW_UPLOAD_REQUEST, SGL) +
10412             sizeof (*tcsge);
10413         if (pt->request_size != pt->sgl_offset)
10414                 NDBG15(("mpi_pre_fw_upload(): Incorrect req size, "
10415                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10416                     pt->request_size, pt->sgl_offset,
10417                     pt->dataout_size));
10418         if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
10419                 NDBG15(("mpi_pre_fw_upload(): Incorrect rep size, "
10420                     "0x%x, should be 0x%x", pt->data_size,
10421                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10422 }
10423 
10424 /*
10425  * Prepare the pt a SAS3 FW_UPLOAD request.
10426  */
10427 static void
10428 mpi_pre_fw_25_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
10429 {
10430         pMpi2FWUploadTCSGE_t tcsge;
10431         pMpi2FWUploadRequest_t req2;
10432         pMpi25FWUploadRequest_t req25;
10433 
10434         /*
10435          * User requests should come in with the Transaction
10436          * context element where the SGL will go. The new firmware
10437          * Doesn't use TCE and has space in the main request for
10438          * this information. So move to the right place.
10439          */
10440         req2 = (pMpi2FWUploadRequest_t)pt->request;
10441         req25 = (pMpi25FWUploadRequest_t)pt->request;
10442         tcsge = (pMpi2FWUploadTCSGE_t)&req2->SGL;
10443         if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
10444             tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
10445                 mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
10446         }
10447         req25->ImageOffset = tcsge->ImageOffset;
10448         req25->ImageSize = tcsge->ImageSize;
10449 
10450         pt->sgl_offset = offsetof(MPI25_FW_UPLOAD_REQUEST, SGL);
10451         if (pt->request_size != pt->sgl_offset)
10452                 NDBG15(("mpi_pre_fw_25_upload(): Incorrect req size, "
10453                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10454                     pt->request_size, pt->sgl_offset,
10455                     pt->dataout_size));
10456         if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
10457                 NDBG15(("mpi_pre_fw_25_upload(): Incorrect rep size, "
10458                     "0x%x, should be 0x%x", pt->data_size,
10459                     (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
10460 }
10461 
10462 /*
10463  * Prepare the pt for an IOC_FACTS request.
10464  */
10465 static void
10466 mpi_pre_ioc_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
10467 {
10468 #ifndef __lock_lint
10469         _NOTE(ARGUNUSED(mpt))
10470 #endif
10471         if (pt->request_size != sizeof (MPI2_IOC_FACTS_REQUEST))
10472                 NDBG15(("mpi_pre_ioc_facts(): Incorrect req size, "
10473                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10474                     pt->request_size,
10475                     (int)sizeof (MPI2_IOC_FACTS_REQUEST),
10476                     pt->dataout_size));
10477         if (pt->data_size != sizeof (MPI2_IOC_FACTS_REPLY))
10478                 NDBG15(("mpi_pre_ioc_facts(): Incorrect rep size, "
10479                     "0x%x, should be 0x%x", pt->data_size,
10480                     (int)sizeof (MPI2_IOC_FACTS_REPLY)));
10481         pt->sgl_offset = (uint16_t)pt->request_size;
10482 }
10483 
10484 /*
10485  * Prepare the pt for a PORT_FACTS request.
10486  */
10487 static void
10488 mpi_pre_port_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
10489 {
10490 #ifndef __lock_lint
10491         _NOTE(ARGUNUSED(mpt))
10492 #endif
10493         if (pt->request_size != sizeof (MPI2_PORT_FACTS_REQUEST))
10494                 NDBG15(("mpi_pre_port_facts(): Incorrect req size, "
10495                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10496                     pt->request_size,
10497                     (int)sizeof (MPI2_PORT_FACTS_REQUEST),
10498                     pt->dataout_size));
10499         if (pt->data_size != sizeof (MPI2_PORT_FACTS_REPLY))
10500                 NDBG15(("mpi_pre_port_facts(): Incorrect rep size, "
10501                     "0x%x, should be 0x%x", pt->data_size,
10502                     (int)sizeof (MPI2_PORT_FACTS_REPLY)));
10503         pt->sgl_offset = (uint16_t)pt->request_size;
10504 }
10505 
10506 /*
10507  * Prepare pt for a SATA_PASSTHROUGH request.
10508  */
10509 static void
10510 mpi_pre_sata_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
10511 {
10512 #ifndef __lock_lint
10513         _NOTE(ARGUNUSED(mpt))
10514 #endif
10515         pt->sgl_offset = offsetof(MPI2_SATA_PASSTHROUGH_REQUEST, SGL);
10516         if (pt->request_size != pt->sgl_offset)
10517                 NDBG15(("mpi_pre_sata_passthrough(): Incorrect req size, "
10518                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10519                     pt->request_size, pt->sgl_offset,
10520                     pt->dataout_size));
10521         if (pt->data_size != sizeof (MPI2_SATA_PASSTHROUGH_REPLY))
10522                 NDBG15(("mpi_pre_sata_passthrough(): Incorrect rep size, "
10523                     "0x%x, should be 0x%x", pt->data_size,
10524                     (int)sizeof (MPI2_SATA_PASSTHROUGH_REPLY)));
10525 }
10526 
10527 static void
10528 mpi_pre_smp_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
10529 {
10530 #ifndef __lock_lint
10531         _NOTE(ARGUNUSED(mpt))
10532 #endif
10533         pt->sgl_offset = offsetof(MPI2_SMP_PASSTHROUGH_REQUEST, SGL);
10534         if (pt->request_size != pt->sgl_offset)
10535                 NDBG15(("mpi_pre_smp_passthrough(): Incorrect req size, "
10536                     "0x%x, should be 0x%x, dataoutsz 0x%x",
10537                     pt->request_size, pt->sgl_offset,
10538                     pt->dataout_size));
10539         if (pt->data_size != sizeof (MPI2_SMP_PASSTHROUGH_REPLY))
10540                 NDBG15(("mpi_pre_smp_passthrough(): Incorrect rep size, "
10541                     "0x%x, should be 0x%x", pt->data_size,
10542                     (int)sizeof (MPI2_SMP_PASSTHROUGH_REPLY)));
10543 }
10544 
10545 /*
10546  * Prepare pt for a CONFIG request.
10547  */
10548 static void
10549 mpi_pre_config(mptsas_t *mpt, mptsas_pt_request_t *pt)
10550 {
10551 #ifndef __lock_lint
10552         _NOTE(ARGUNUSED(mpt))
10553 #endif
10554         pt->sgl_offset = offsetof(MPI2_CONFIG_REQUEST, PageBufferSGE);
10555         if (pt->request_size != pt->sgl_offset)
10556                 NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
10557                     "should be 0x%x, dataoutsz 0x%x", pt->request_size,
10558                     pt->sgl_offset, pt->dataout_size));
10559         if (pt->data_size != sizeof (MPI2_CONFIG_REPLY))
10560                 NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
10561                     "should be 0x%x", pt->data_size,
10562                     (int)sizeof (MPI2_CONFIG_REPLY)));
10563         pt->simple = 1;
10564 }
10565 
10566 /*
10567  * Prepare pt for a SCSI_IO_REQ request.
10568  */
10569 static void
10570 mpi_pre_scsi_io_req(mptsas_t *mpt, mptsas_pt_request_t *pt)
10571 {
10572 #ifndef __lock_lint
10573         _NOTE(ARGUNUSED(mpt))
10574 #endif
10575         pt->sgl_offset = offsetof(MPI2_SCSI_IO_REQUEST, SGL);
10576         if (pt->request_size != pt->sgl_offset)
10577                 NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
10578                     "should be 0x%x, dataoutsz 0x%x", pt->request_size,
10579                     pt->sgl_offset,
10580                     pt->dataout_size));
10581         if (pt->data_size != sizeof (MPI2_SCSI_IO_REPLY))
10582                 NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
10583                     "should be 0x%x", pt->data_size,
10584                     (int)sizeof (MPI2_SCSI_IO_REPLY)));
10585 }
10586 
10587 /*
10588  * Prepare the mptsas_cmd for a SAS_IO_UNIT_CONTROL request.
10589  */
10590 static void
10591 mpi_pre_sas_io_unit_control(mptsas_t *mpt, mptsas_pt_request_t *pt)
10592 {
10593 #ifndef __lock_lint
10594         _NOTE(ARGUNUSED(mpt))
10595 #endif
10596         pt->sgl_offset = (uint16_t)pt->request_size;
10597 }
10598 
10599 /*
10600  * A set of functions to prepare an mptsas_cmd for the various
10601  * supported requests.
10602  */
10603 static struct mptsas_func {
10604         U8              Function;
10605         char            *Name;
10606         mptsas_pre_f    *f_pre;
10607 } mptsas_func_list[] = {
10608         { MPI2_FUNCTION_IOC_FACTS, "IOC_FACTS",         mpi_pre_ioc_facts },
10609         { MPI2_FUNCTION_PORT_FACTS, "PORT_FACTS",       mpi_pre_port_facts },
10610         { MPI2_FUNCTION_FW_DOWNLOAD, "FW_DOWNLOAD",     mpi_pre_fw_download },
10611         { MPI2_FUNCTION_FW_UPLOAD, "FW_UPLOAD",         mpi_pre_fw_upload },
10612         { MPI2_FUNCTION_SATA_PASSTHROUGH, "SATA_PASSTHROUGH",
10613             mpi_pre_sata_passthrough },
10614         { MPI2_FUNCTION_SMP_PASSTHROUGH, "SMP_PASSTHROUGH",
10615             mpi_pre_smp_passthrough},
10616         { MPI2_FUNCTION_SCSI_IO_REQUEST, "SCSI_IO_REQUEST",
10617             mpi_pre_scsi_io_req},
10618         { MPI2_FUNCTION_CONFIG, "CONFIG",               mpi_pre_config},
10619         { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL, "SAS_IO_UNIT_CONTROL",
10620             mpi_pre_sas_io_unit_control },
10621         { 0xFF, NULL,                           NULL } /* list end */
10622 };
10623 
10624 static void
10625 mptsas_prep_sgl_offset(mptsas_t *mpt, mptsas_pt_request_t *pt)
10626 {
10627         pMPI2RequestHeader_t    hdr;
10628         struct mptsas_func      *f;
10629 
10630         hdr = (pMPI2RequestHeader_t)pt->request;
10631 
10632         for (f = mptsas_func_list; f->f_pre != NULL; f++) {
10633                 if (hdr->Function == f->Function) {
10634                         f->f_pre(mpt, pt);
10635                         NDBG15(("mptsas_prep_sgl_offset: Function %s,"
10636                             " sgl_offset 0x%x", f->Name,
10637                             pt->sgl_offset));
10638                         return;
10639                 }
10640         }
10641         NDBG15(("mptsas_prep_sgl_offset: Unknown Function 0x%02x,"
10642             " returning req_size 0x%x for sgl_offset",
10643             hdr->Function, pt->request_size));
10644         pt->sgl_offset = (uint16_t)pt->request_size;
10645 }
10646 
10647 
10648 static int
10649 mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
10650     uint8_t *data, uint32_t request_size, uint32_t reply_size,
10651     uint32_t data_size, uint32_t direction, uint8_t *dataout,
10652     uint32_t dataout_size, short timeout, int mode)
10653 {
10654         mptsas_pt_request_t             pt;
10655         mptsas_dma_alloc_state_t        data_dma_state;
10656         mptsas_dma_alloc_state_t        dataout_dma_state;
10657         caddr_t                         memp;
10658         mptsas_cmd_t                    *cmd = NULL;
10659         struct scsi_pkt                 *pkt;
10660         uint32_t                        reply_len = 0, sense_len = 0;
10661         pMPI2RequestHeader_t            request_hdrp;
10662         pMPI2RequestHeader_t            request_msg;
10663         pMPI2DefaultReply_t             reply_msg;
10664         Mpi2SCSIIOReply_t               rep_msg;
10665         int                             i, status = 0, pt_flags = 0, rv = 0;
10666         int                             rvalue;
10667         uint8_t                         function;
10668 
10669         ASSERT(mutex_owned(&mpt->m_mutex));
10670 
10671         reply_msg = (pMPI2DefaultReply_t)(&rep_msg);
10672         bzero(reply_msg, sizeof (MPI2_DEFAULT_REPLY));
10673         request_msg = kmem_zalloc(request_size, KM_SLEEP);
10674 
10675         mutex_exit(&mpt->m_mutex);
10676         /*
10677          * copy in the request buffer since it could be used by
10678          * another thread when the pt request into waitq
10679          */
10680         if (ddi_copyin(request, request_msg, request_size, mode)) {
10681                 mutex_enter(&mpt->m_mutex);
10682                 status = EFAULT;
10683                 mptsas_log(mpt, CE_WARN, "failed to copy request data");
10684                 goto out;
10685         }
10686         mutex_enter(&mpt->m_mutex);
10687 
10688         function = request_msg->Function;
10689         if (function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
10690                 pMpi2SCSITaskManagementRequest_t        task;
10691                 task = (pMpi2SCSITaskManagementRequest_t)request_msg;
10692                 mptsas_setup_bus_reset_delay(mpt);
10693                 rv = mptsas_ioc_task_management(mpt, task->TaskType,
10694                     task->DevHandle, (int)task->LUN[1], reply, reply_size,
10695                     mode);
10696 
10697                 if (rv != TRUE) {
10698                         status = EIO;
10699                         mptsas_log(mpt, CE_WARN, "task management failed");
10700                 }
10701                 goto out;
10702         }
10703 
10704         if (data_size != 0) {
10705                 data_dma_state.size = data_size;
10706                 if (mptsas_dma_alloc(mpt, &data_dma_state) != DDI_SUCCESS) {
10707                         status = ENOMEM;
10708                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10709                             "resource");
10710                         goto out;
10711                 }
10712                 pt_flags |= MPTSAS_DATA_ALLOCATED;
10713                 if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10714                         mutex_exit(&mpt->m_mutex);
10715                         for (i = 0; i < data_size; i++) {
10716                                 if (ddi_copyin(data + i, (uint8_t *)
10717                                     data_dma_state.memp + i, 1, mode)) {
10718                                         mutex_enter(&mpt->m_mutex);
10719                                         status = EFAULT;
10720                                         mptsas_log(mpt, CE_WARN, "failed to "
10721                                             "copy read data");
10722                                         goto out;
10723                                 }
10724                         }
10725                         mutex_enter(&mpt->m_mutex);
10726                 }
10727         } else {
10728                 bzero(&data_dma_state, sizeof (data_dma_state));
10729         }
10730 
10731         if (dataout_size != 0) {
10732                 dataout_dma_state.size = dataout_size;
10733                 if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
10734                         status = ENOMEM;
10735                         mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
10736                             "resource");
10737                         goto out;
10738                 }
10739                 pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
10740                 mutex_exit(&mpt->m_mutex);
10741                 for (i = 0; i < dataout_size; i++) {
10742                         if (ddi_copyin(dataout + i, (uint8_t *)
10743                             dataout_dma_state.memp + i, 1, mode)) {
10744                                 mutex_enter(&mpt->m_mutex);
10745                                 mptsas_log(mpt, CE_WARN, "failed to copy out"
10746                                     " data");
10747                                 status = EFAULT;
10748                                 goto out;
10749                         }
10750                 }
10751                 mutex_enter(&mpt->m_mutex);
10752         } else {
10753                 bzero(&dataout_dma_state, sizeof (dataout_dma_state));
10754         }
10755 
10756         if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
10757                 status = EAGAIN;
10758                 mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
10759                 goto out;
10760         }
10761         pt_flags |= MPTSAS_REQUEST_POOL_CMD;
10762 
10763         bzero((caddr_t)cmd, sizeof (*cmd));
10764         bzero((caddr_t)pkt, scsi_pkt_size());
10765         bzero((caddr_t)&pt, sizeof (pt));
10766 
10767         cmd->ioc_cmd_slot = (uint32_t)(rvalue);
10768 
10769         pt.request = (uint8_t *)request_msg;
10770         pt.direction = direction;
10771         pt.simple = 0;
10772         pt.request_size = request_size;
10773         pt.data_size = data_size;
10774         pt.dataout_size = dataout_size;
10775         pt.data_cookie = data_dma_state.cookie;
10776         pt.dataout_cookie = dataout_dma_state.cookie;
10777         mptsas_prep_sgl_offset(mpt, &pt);
10778 
10779         /*
10780          * Form a blank cmd/pkt to store the acknowledgement message
10781          */
10782         pkt->pkt_cdbp                = (opaque_t)&cmd->cmd_cdb[0];
10783         pkt->pkt_scbp                = (opaque_t)&cmd->cmd_scb;
10784         pkt->pkt_ha_private  = (opaque_t)&pt;
10785         pkt->pkt_flags               = FLAG_HEAD;
10786         pkt->pkt_time                = timeout;
10787         cmd->cmd_pkt         = pkt;
10788         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_PASSTHRU;
10789 
10790         /*
10791          * Save the command in a slot
10792          */
10793         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
10794                 /*
10795                  * Once passthru command get slot, set cmd_flags
10796                  * CFLAG_PREPARED.
10797                  */
10798                 cmd->cmd_flags |= CFLAG_PREPARED;
10799                 mptsas_start_passthru(mpt, cmd);
10800         } else {
10801                 mptsas_waitq_add(mpt, cmd);
10802         }
10803 
10804         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
10805                 cv_wait(&mpt->m_passthru_cv, &mpt->m_mutex);
10806         }
10807 
10808         if (cmd->cmd_flags & CFLAG_PREPARED) {
10809                 memp = mpt->m_req_frame + (mpt->m_req_frame_size *
10810                     cmd->cmd_slot);
10811                 request_hdrp = (pMPI2RequestHeader_t)memp;
10812         }
10813 
10814         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
10815                 status = ETIMEDOUT;
10816                 mptsas_log(mpt, CE_WARN, "passthrough command timeout");
10817                 pt_flags |= MPTSAS_CMD_TIMEOUT;
10818                 goto out;
10819         }
10820 
10821         if (cmd->cmd_rfm) {
10822                 /*
10823                  * cmd_rfm is zero means the command reply is a CONTEXT
10824                  * reply and no PCI Write to post the free reply SMFA
10825                  * because no reply message frame is used.
10826                  * cmd_rfm is non-zero means the reply is a ADDRESS
10827                  * reply and reply message frame is used.
10828                  */
10829                 pt_flags |= MPTSAS_ADDRESS_REPLY;
10830                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
10831                     DDI_DMA_SYNC_FORCPU);
10832                 reply_msg = (pMPI2DefaultReply_t)
10833                     (mpt->m_reply_frame + (cmd->cmd_rfm -
10834                     mpt->m_reply_frame_dma_addr));
10835         }
10836 
10837         mptsas_fma_check(mpt, cmd);
10838         if (pkt->pkt_reason == CMD_TRAN_ERR) {
10839                 status = EAGAIN;
10840                 mptsas_log(mpt, CE_WARN, "passthru fma error");
10841                 goto out;
10842         }
10843         if (pkt->pkt_reason == CMD_RESET) {
10844                 status = EAGAIN;
10845                 mptsas_log(mpt, CE_WARN, "ioc reset abort passthru");
10846                 goto out;
10847         }
10848 
10849         if (pkt->pkt_reason == CMD_INCOMPLETE) {
10850                 status = EIO;
10851                 mptsas_log(mpt, CE_WARN, "passthrough command incomplete");
10852                 goto out;
10853         }
10854 
10855         mutex_exit(&mpt->m_mutex);
10856         if (cmd->cmd_flags & CFLAG_PREPARED) {
10857                 function = request_hdrp->Function;
10858                 if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
10859                     (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
10860                         reply_len = sizeof (MPI2_SCSI_IO_REPLY);
10861                         sense_len = reply_size - reply_len;
10862                 } else {
10863                         reply_len = reply_size;
10864                         sense_len = 0;
10865                 }
10866 
10867                 for (i = 0; i < reply_len; i++) {
10868                         if (ddi_copyout((uint8_t *)reply_msg + i, reply + i, 1,
10869                             mode)) {
10870                                 mutex_enter(&mpt->m_mutex);
10871                                 status = EFAULT;
10872                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10873                                     "reply data");
10874                                 goto out;
10875                         }
10876                 }
10877                 for (i = 0; i < sense_len; i++) {
10878                         if (ddi_copyout((uint8_t *)request_hdrp + 64 + i,
10879                             reply + reply_len + i, 1, mode)) {
10880                                 mutex_enter(&mpt->m_mutex);
10881                                 status = EFAULT;
10882                                 mptsas_log(mpt, CE_WARN, "failed to copy out "
10883                                     "sense data");
10884                                 goto out;
10885                         }
10886                 }
10887         }
10888 
10889         if (data_size) {
10890                 if (direction != MPTSAS_PASS_THRU_DIRECTION_WRITE) {
10891                         (void) ddi_dma_sync(data_dma_state.handle, 0, 0,
10892                             DDI_DMA_SYNC_FORCPU);
10893                         for (i = 0; i < data_size; i++) {
10894                                 if (ddi_copyout((uint8_t *)(
10895                                     data_dma_state.memp + i), data + i,  1,
10896                                     mode)) {
10897                                         mutex_enter(&mpt->m_mutex);
10898                                         status = EFAULT;
10899                                         mptsas_log(mpt, CE_WARN, "failed to "
10900                                             "copy out the reply data");
10901                                         goto out;
10902                                 }
10903                         }
10904                 }
10905         }
10906         mutex_enter(&mpt->m_mutex);
10907 out:
10908         /*
10909          * Put the reply frame back on the free queue, increment the free
10910          * index, and write the new index to the free index register.  But only
10911          * if this reply is an ADDRESS reply.
10912          */
10913         if (pt_flags & MPTSAS_ADDRESS_REPLY) {
10914                 ddi_put32(mpt->m_acc_free_queue_hdl,
10915                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
10916                     cmd->cmd_rfm);
10917                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
10918                     DDI_DMA_SYNC_FORDEV);
10919                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
10920                         mpt->m_free_index = 0;
10921                 }
10922                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
10923                     mpt->m_free_index);
10924         }
10925         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
10926                 mptsas_remove_cmd(mpt, cmd);
10927                 pt_flags &= (~MPTSAS_REQUEST_POOL_CMD);
10928         }
10929         if (pt_flags & MPTSAS_REQUEST_POOL_CMD)
10930                 mptsas_return_to_pool(mpt, cmd);
10931         if (pt_flags & MPTSAS_DATA_ALLOCATED) {
10932                 if (mptsas_check_dma_handle(data_dma_state.handle) !=
10933                     DDI_SUCCESS) {
10934                         ddi_fm_service_impact(mpt->m_dip,
10935                             DDI_SERVICE_UNAFFECTED);
10936                         status = EFAULT;
10937                 }
10938                 mptsas_dma_free(&data_dma_state);
10939         }
10940         if (pt_flags & MPTSAS_DATAOUT_ALLOCATED) {
10941                 if (mptsas_check_dma_handle(dataout_dma_state.handle) !=
10942                     DDI_SUCCESS) {
10943                         ddi_fm_service_impact(mpt->m_dip,
10944                             DDI_SERVICE_UNAFFECTED);
10945                         status = EFAULT;
10946                 }
10947                 mptsas_dma_free(&dataout_dma_state);
10948         }
10949         if (pt_flags & MPTSAS_CMD_TIMEOUT) {
10950                 if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
10951                         mptsas_log(mpt, CE_WARN, "mptsas_restart_ioc failed");
10952                 }
10953         }
10954         if (request_msg)
10955                 kmem_free(request_msg, request_size);
10956 
10957         return (status);
10958 }
10959 
10960 static int
10961 mptsas_pass_thru(mptsas_t *mpt, mptsas_pass_thru_t *data, int mode)
10962 {
10963         /*
10964          * If timeout is 0, set timeout to default of 60 seconds.
10965          */
10966         if (data->Timeout == 0) {
10967                 data->Timeout = MPTSAS_PASS_THRU_TIME_DEFAULT;
10968         }
10969 
10970         if (((data->DataSize == 0) &&
10971             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_NONE)) ||
10972             ((data->DataSize != 0) &&
10973             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_READ) ||
10974             (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_WRITE) ||
10975             ((data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) &&
10976             (data->DataOutSize != 0))))) {
10977                 if (data->DataDirection == MPTSAS_PASS_THRU_DIRECTION_BOTH) {
10978                         data->DataDirection = MPTSAS_PASS_THRU_DIRECTION_READ;
10979                 } else {
10980                         data->DataOutSize = 0;
10981                 }
10982                 /*
10983                  * Send passthru request messages
10984                  */
10985                 return (mptsas_do_passthru(mpt,
10986                     (uint8_t *)((uintptr_t)data->PtrRequest),
10987                     (uint8_t *)((uintptr_t)data->PtrReply),
10988                     (uint8_t *)((uintptr_t)data->PtrData),
10989                     data->RequestSize, data->ReplySize,
10990                     data->DataSize, data->DataDirection,
10991                     (uint8_t *)((uintptr_t)data->PtrDataOut),
10992                     data->DataOutSize, data->Timeout, mode));
10993         } else {
10994                 return (EINVAL);
10995         }
10996 }
10997 
10998 static uint8_t
10999 mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
11000 {
11001         uint8_t index;
11002 
11003         for (index = 0; index < MPI2_DIAG_BUF_TYPE_COUNT; index++) {
11004                 if (mpt->m_fw_diag_buffer_list[index].unique_id == unique_id) {
11005                         return (index);
11006                 }
11007         }
11008 
11009         return (MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND);
11010 }
11011 
11012 static void
11013 mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd)
11014 {
11015         pMpi2DiagBufferPostRequest_t    pDiag_post_msg;
11016         pMpi2DiagReleaseRequest_t       pDiag_release_msg;
11017         struct scsi_pkt                 *pkt = cmd->cmd_pkt;
11018         mptsas_diag_request_t           *diag = pkt->pkt_ha_private;
11019         uint32_t                        request_desc_low, i;
11020 
11021         ASSERT(mutex_owned(&mpt->m_mutex));
11022 
11023         /*
11024          * Form the diag message depending on the post or release function.
11025          */
11026         if (diag->function == MPI2_FUNCTION_DIAG_BUFFER_POST) {
11027                 pDiag_post_msg = (pMpi2DiagBufferPostRequest_t)
11028                     (mpt->m_req_frame + (mpt->m_req_frame_size *
11029                     cmd->cmd_slot));
11030                 bzero(pDiag_post_msg, mpt->m_req_frame_size);
11031                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->Function,
11032                     diag->function);
11033                 ddi_put8(mpt->m_acc_req_frame_hdl, &pDiag_post_msg->BufferType,
11034                     diag->pBuffer->buffer_type);
11035                 ddi_put8(mpt->m_acc_req_frame_hdl,
11036                     &pDiag_post_msg->ExtendedType,
11037                     diag->pBuffer->extended_type);
11038                 ddi_put32(mpt->m_acc_req_frame_hdl,
11039                     &pDiag_post_msg->BufferLength,
11040                     diag->pBuffer->buffer_data.size);
11041                 for (i = 0; i < (sizeof (pDiag_post_msg->ProductSpecific) / 4);
11042                     i++) {
11043                         ddi_put32(mpt->m_acc_req_frame_hdl,
11044                             &pDiag_post_msg->ProductSpecific[i],
11045                             diag->pBuffer->product_specific[i]);
11046                 }
11047                 ddi_put32(mpt->m_acc_req_frame_hdl,
11048                     &pDiag_post_msg->BufferAddress.Low,
11049                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
11050                     & 0xffffffffull));
11051                 ddi_put32(mpt->m_acc_req_frame_hdl,
11052                     &pDiag_post_msg->BufferAddress.High,
11053                     (uint32_t)(diag->pBuffer->buffer_data.cookie.dmac_laddress
11054                     >> 32));
11055         } else {
11056                 pDiag_release_msg = (pMpi2DiagReleaseRequest_t)
11057                     (mpt->m_req_frame + (mpt->m_req_frame_size *
11058                     cmd->cmd_slot));
11059                 bzero(pDiag_release_msg, mpt->m_req_frame_size);
11060                 ddi_put8(mpt->m_acc_req_frame_hdl,
11061                     &pDiag_release_msg->Function, diag->function);
11062                 ddi_put8(mpt->m_acc_req_frame_hdl,
11063                     &pDiag_release_msg->BufferType,
11064                     diag->pBuffer->buffer_type);
11065         }
11066 
11067         /*
11068          * Send the message
11069          */
11070         (void) ddi_dma_sync(mpt->m_dma_req_frame_hdl, 0, 0,
11071             DDI_DMA_SYNC_FORDEV);
11072         request_desc_low = (cmd->cmd_slot << 16) +
11073             MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
11074         cmd->cmd_rfm = NULL;
11075         MPTSAS_START_CMD(mpt, request_desc_low, 0);
11076         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
11077             DDI_SUCCESS) ||
11078             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
11079             DDI_SUCCESS)) {
11080                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11081         }
11082 }
11083 
11084 static int
11085 mptsas_post_fw_diag_buffer(mptsas_t *mpt,
11086     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code)
11087 {
11088         mptsas_diag_request_t           diag;
11089         int                             status, slot_num, post_flags = 0;
11090         mptsas_cmd_t                    *cmd = NULL;
11091         struct scsi_pkt                 *pkt;
11092         pMpi2DiagBufferPostReply_t      reply;
11093         uint16_t                        iocstatus;
11094         uint32_t                        iocloginfo, transfer_length;
11095 
11096         /*
11097          * If buffer is not enabled, just leave.
11098          */
11099         *return_code = MPTSAS_FW_DIAG_ERROR_POST_FAILED;
11100         if (!pBuffer->enabled) {
11101                 status = DDI_FAILURE;
11102                 goto out;
11103         }
11104 
11105         /*
11106          * Clear some flags initially.
11107          */
11108         pBuffer->force_release = FALSE;
11109         pBuffer->valid_data = FALSE;
11110         pBuffer->owned_by_firmware = FALSE;
11111 
11112         /*
11113          * Get a cmd buffer from the cmd buffer pool
11114          */
11115         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
11116                 status = DDI_FAILURE;
11117                 mptsas_log(mpt, CE_NOTE, "command pool is full: Post FW Diag");
11118                 goto out;
11119         }
11120         post_flags |= MPTSAS_REQUEST_POOL_CMD;
11121 
11122         bzero((caddr_t)cmd, sizeof (*cmd));
11123         bzero((caddr_t)pkt, scsi_pkt_size());
11124 
11125         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
11126 
11127         diag.pBuffer = pBuffer;
11128         diag.function = MPI2_FUNCTION_DIAG_BUFFER_POST;
11129 
11130         /*
11131          * Form a blank cmd/pkt to store the acknowledgement message
11132          */
11133         pkt->pkt_ha_private  = (opaque_t)&diag;
11134         pkt->pkt_flags               = FLAG_HEAD;
11135         pkt->pkt_time                = 60;
11136         cmd->cmd_pkt         = pkt;
11137         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
11138 
11139         /*
11140          * Save the command in a slot
11141          */
11142         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
11143                 /*
11144                  * Once passthru command get slot, set cmd_flags
11145                  * CFLAG_PREPARED.
11146                  */
11147                 cmd->cmd_flags |= CFLAG_PREPARED;
11148                 mptsas_start_diag(mpt, cmd);
11149         } else {
11150                 mptsas_waitq_add(mpt, cmd);
11151         }
11152 
11153         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
11154                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
11155         }
11156 
11157         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
11158                 status = DDI_FAILURE;
11159                 mptsas_log(mpt, CE_WARN, "Post FW Diag command timeout");
11160                 goto out;
11161         }
11162 
11163         /*
11164          * cmd_rfm points to the reply message if a reply was given.  Check the
11165          * IOCStatus to make sure everything went OK with the FW diag request
11166          * and set buffer flags.
11167          */
11168         if (cmd->cmd_rfm) {
11169                 post_flags |= MPTSAS_ADDRESS_REPLY;
11170                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11171                     DDI_DMA_SYNC_FORCPU);
11172                 reply = (pMpi2DiagBufferPostReply_t)(mpt->m_reply_frame +
11173                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
11174 
11175                 /*
11176                  * Get the reply message data
11177                  */
11178                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
11179                     &reply->IOCStatus);
11180                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
11181                     &reply->IOCLogInfo);
11182                 transfer_length = ddi_get32(mpt->m_acc_reply_frame_hdl,
11183                     &reply->TransferLength);
11184 
11185                 /*
11186                  * If post failed quit.
11187                  */
11188                 if (iocstatus != MPI2_IOCSTATUS_SUCCESS) {
11189                         status = DDI_FAILURE;
11190                         NDBG13(("post FW Diag Buffer failed: IOCStatus=0x%x, "
11191                             "IOCLogInfo=0x%x, TransferLength=0x%x", iocstatus,
11192                             iocloginfo, transfer_length));
11193                         goto out;
11194                 }
11195 
11196                 /*
11197                  * Post was successful.
11198                  */
11199                 pBuffer->valid_data = TRUE;
11200                 pBuffer->owned_by_firmware = TRUE;
11201                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11202                 status = DDI_SUCCESS;
11203         }
11204 
11205 out:
11206         /*
11207          * Put the reply frame back on the free queue, increment the free
11208          * index, and write the new index to the free index register.  But only
11209          * if this reply is an ADDRESS reply.
11210          */
11211         if (post_flags & MPTSAS_ADDRESS_REPLY) {
11212                 ddi_put32(mpt->m_acc_free_queue_hdl,
11213                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11214                     cmd->cmd_rfm);
11215                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11216                     DDI_DMA_SYNC_FORDEV);
11217                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11218                         mpt->m_free_index = 0;
11219                 }
11220                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11221                     mpt->m_free_index);
11222         }
11223         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11224                 mptsas_remove_cmd(mpt, cmd);
11225                 post_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11226         }
11227         if (post_flags & MPTSAS_REQUEST_POOL_CMD) {
11228                 mptsas_return_to_pool(mpt, cmd);
11229         }
11230 
11231         return (status);
11232 }
11233 
11234 static int
11235 mptsas_release_fw_diag_buffer(mptsas_t *mpt,
11236     mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
11237     uint32_t diag_type)
11238 {
11239         mptsas_diag_request_t   diag;
11240         int                     status, slot_num, rel_flags = 0;
11241         mptsas_cmd_t            *cmd = NULL;
11242         struct scsi_pkt         *pkt;
11243         pMpi2DiagReleaseReply_t reply;
11244         uint16_t                iocstatus;
11245         uint32_t                iocloginfo;
11246 
11247         /*
11248          * If buffer is not enabled, just leave.
11249          */
11250         *return_code = MPTSAS_FW_DIAG_ERROR_RELEASE_FAILED;
11251         if (!pBuffer->enabled) {
11252                 mptsas_log(mpt, CE_NOTE, "This buffer type is not supported "
11253                     "by the IOC");
11254                 status = DDI_FAILURE;
11255                 goto out;
11256         }
11257 
11258         /*
11259          * Clear some flags initially.
11260          */
11261         pBuffer->force_release = FALSE;
11262         pBuffer->valid_data = FALSE;
11263         pBuffer->owned_by_firmware = FALSE;
11264 
11265         /*
11266          * Get a cmd buffer from the cmd buffer pool
11267          */
11268         if ((slot_num = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
11269                 status = DDI_FAILURE;
11270                 mptsas_log(mpt, CE_NOTE, "command pool is full: Release FW "
11271                     "Diag");
11272                 goto out;
11273         }
11274         rel_flags |= MPTSAS_REQUEST_POOL_CMD;
11275 
11276         bzero((caddr_t)cmd, sizeof (*cmd));
11277         bzero((caddr_t)pkt, scsi_pkt_size());
11278 
11279         cmd->ioc_cmd_slot = (uint32_t)(slot_num);
11280 
11281         diag.pBuffer = pBuffer;
11282         diag.function = MPI2_FUNCTION_DIAG_RELEASE;
11283 
11284         /*
11285          * Form a blank cmd/pkt to store the acknowledgement message
11286          */
11287         pkt->pkt_ha_private  = (opaque_t)&diag;
11288         pkt->pkt_flags               = FLAG_HEAD;
11289         pkt->pkt_time                = 60;
11290         cmd->cmd_pkt         = pkt;
11291         cmd->cmd_flags               = CFLAG_CMDIOC | CFLAG_FW_DIAG;
11292 
11293         /*
11294          * Save the command in a slot
11295          */
11296         if (mptsas_save_cmd(mpt, cmd) == TRUE) {
11297                 /*
11298                  * Once passthru command get slot, set cmd_flags
11299                  * CFLAG_PREPARED.
11300                  */
11301                 cmd->cmd_flags |= CFLAG_PREPARED;
11302                 mptsas_start_diag(mpt, cmd);
11303         } else {
11304                 mptsas_waitq_add(mpt, cmd);
11305         }
11306 
11307         while ((cmd->cmd_flags & CFLAG_FINISHED) == 0) {
11308                 cv_wait(&mpt->m_fw_diag_cv, &mpt->m_mutex);
11309         }
11310 
11311         if (cmd->cmd_flags & CFLAG_TIMEOUT) {
11312                 status = DDI_FAILURE;
11313                 mptsas_log(mpt, CE_WARN, "Release FW Diag command timeout");
11314                 goto out;
11315         }
11316 
11317         /*
11318          * cmd_rfm points to the reply message if a reply was given.  Check the
11319          * IOCStatus to make sure everything went OK with the FW diag request
11320          * and set buffer flags.
11321          */
11322         if (cmd->cmd_rfm) {
11323                 rel_flags |= MPTSAS_ADDRESS_REPLY;
11324                 (void) ddi_dma_sync(mpt->m_dma_reply_frame_hdl, 0, 0,
11325                     DDI_DMA_SYNC_FORCPU);
11326                 reply = (pMpi2DiagReleaseReply_t)(mpt->m_reply_frame +
11327                     (cmd->cmd_rfm - mpt->m_reply_frame_dma_addr));
11328 
11329                 /*
11330                  * Get the reply message data
11331                  */
11332                 iocstatus = ddi_get16(mpt->m_acc_reply_frame_hdl,
11333                     &reply->IOCStatus);
11334                 iocloginfo = ddi_get32(mpt->m_acc_reply_frame_hdl,
11335                     &reply->IOCLogInfo);
11336 
11337                 /*
11338                  * If release failed quit.
11339                  */
11340                 if ((iocstatus != MPI2_IOCSTATUS_SUCCESS) ||
11341                     pBuffer->owned_by_firmware) {
11342                         status = DDI_FAILURE;
11343                         NDBG13(("release FW Diag Buffer failed: "
11344                             "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
11345                             iocloginfo));
11346                         goto out;
11347                 }
11348 
11349                 /*
11350                  * Release was successful.
11351                  */
11352                 *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11353                 status = DDI_SUCCESS;
11354 
11355                 /*
11356                  * If this was for an UNREGISTER diag type command, clear the
11357                  * unique ID.
11358                  */
11359                 if (diag_type == MPTSAS_FW_DIAG_TYPE_UNREGISTER) {
11360                         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11361                 }
11362         }
11363 
11364 out:
11365         /*
11366          * Put the reply frame back on the free queue, increment the free
11367          * index, and write the new index to the free index register.  But only
11368          * if this reply is an ADDRESS reply.
11369          */
11370         if (rel_flags & MPTSAS_ADDRESS_REPLY) {
11371                 ddi_put32(mpt->m_acc_free_queue_hdl,
11372                     &((uint32_t *)(void *)mpt->m_free_queue)[mpt->m_free_index],
11373                     cmd->cmd_rfm);
11374                 (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
11375                     DDI_DMA_SYNC_FORDEV);
11376                 if (++mpt->m_free_index == mpt->m_free_queue_depth) {
11377                         mpt->m_free_index = 0;
11378                 }
11379                 ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex,
11380                     mpt->m_free_index);
11381         }
11382         if (cmd && (cmd->cmd_flags & CFLAG_PREPARED)) {
11383                 mptsas_remove_cmd(mpt, cmd);
11384                 rel_flags &= (~MPTSAS_REQUEST_POOL_CMD);
11385         }
11386         if (rel_flags & MPTSAS_REQUEST_POOL_CMD) {
11387                 mptsas_return_to_pool(mpt, cmd);
11388         }
11389 
11390         return (status);
11391 }
11392 
11393 static int
11394 mptsas_diag_register(mptsas_t *mpt, mptsas_fw_diag_register_t *diag_register,
11395     uint32_t *return_code)
11396 {
11397         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11398         uint8_t                         extended_type, buffer_type, i;
11399         uint32_t                        buffer_size;
11400         uint32_t                        unique_id;
11401         int                             status;
11402 
11403         ASSERT(mutex_owned(&mpt->m_mutex));
11404 
11405         extended_type = diag_register->ExtendedType;
11406         buffer_type = diag_register->BufferType;
11407         buffer_size = diag_register->RequestedBufferSize;
11408         unique_id = diag_register->UniqueId;
11409 
11410         /*
11411          * Check for valid buffer type
11412          */
11413         if (buffer_type >= MPI2_DIAG_BUF_TYPE_COUNT) {
11414                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11415                 return (DDI_FAILURE);
11416         }
11417 
11418         /*
11419          * Get the current buffer and look up the unique ID.  The unique ID
11420          * should not be found.  If it is, the ID is already in use.
11421          */
11422         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11423         pBuffer = &mpt->m_fw_diag_buffer_list[buffer_type];
11424         if (i != MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11425                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11426                 return (DDI_FAILURE);
11427         }
11428 
11429         /*
11430          * The buffer's unique ID should not be registered yet, and the given
11431          * unique ID cannot be 0.
11432          */
11433         if ((pBuffer->unique_id != MPTSAS_FW_DIAG_INVALID_UID) ||
11434             (unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11435                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11436                 return (DDI_FAILURE);
11437         }
11438 
11439         /*
11440          * If this buffer is already posted as immediate, just change owner.
11441          */
11442         if (pBuffer->immediate && pBuffer->owned_by_firmware &&
11443             (pBuffer->unique_id == MPTSAS_FW_DIAG_INVALID_UID)) {
11444                 pBuffer->immediate = FALSE;
11445                 pBuffer->unique_id = unique_id;
11446                 return (DDI_SUCCESS);
11447         }
11448 
11449         /*
11450          * Post a new buffer after checking if it's enabled.  The DMA buffer
11451          * that is allocated will be contiguous (sgl_len = 1).
11452          */
11453         if (!pBuffer->enabled) {
11454                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11455                 return (DDI_FAILURE);
11456         }
11457         bzero(&pBuffer->buffer_data, sizeof (mptsas_dma_alloc_state_t));
11458         pBuffer->buffer_data.size = buffer_size;
11459         if (mptsas_dma_alloc(mpt, &pBuffer->buffer_data) != DDI_SUCCESS) {
11460                 mptsas_log(mpt, CE_WARN, "failed to alloc DMA resource for "
11461                     "diag buffer: size = %d bytes", buffer_size);
11462                 *return_code = MPTSAS_FW_DIAG_ERROR_NO_BUFFER;
11463                 return (DDI_FAILURE);
11464         }
11465 
11466         /*
11467          * Copy the given info to the diag buffer and post the buffer.
11468          */
11469         pBuffer->buffer_type = buffer_type;
11470         pBuffer->immediate = FALSE;
11471         if (buffer_type == MPI2_DIAG_BUF_TYPE_TRACE) {
11472                 for (i = 0; i < (sizeof (pBuffer->product_specific) / 4);
11473                     i++) {
11474                         pBuffer->product_specific[i] =
11475                             diag_register->ProductSpecific[i];
11476                 }
11477         }
11478         pBuffer->extended_type = extended_type;
11479         pBuffer->unique_id = unique_id;
11480         status = mptsas_post_fw_diag_buffer(mpt, pBuffer, return_code);
11481 
11482         if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11483             DDI_SUCCESS) {
11484                 mptsas_log(mpt, CE_WARN, "Check of DMA handle failed in "
11485                     "mptsas_diag_register.");
11486                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
11487                         status = DDI_FAILURE;
11488         }
11489 
11490         /*
11491          * In case there was a failure, free the DMA buffer.
11492          */
11493         if (status == DDI_FAILURE) {
11494                 mptsas_dma_free(&pBuffer->buffer_data);
11495         }
11496 
11497         return (status);
11498 }
11499 
11500 static int
11501 mptsas_diag_unregister(mptsas_t *mpt,
11502     mptsas_fw_diag_unregister_t *diag_unregister, uint32_t *return_code)
11503 {
11504         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11505         uint8_t                         i;
11506         uint32_t                        unique_id;
11507         int                             status;
11508 
11509         ASSERT(mutex_owned(&mpt->m_mutex));
11510 
11511         unique_id = diag_unregister->UniqueId;
11512 
11513         /*
11514          * Get the current buffer and look up the unique ID.  The unique ID
11515          * should be there.
11516          */
11517         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11518         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11519                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11520                 return (DDI_FAILURE);
11521         }
11522 
11523         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11524 
11525         /*
11526          * Try to release the buffer from FW before freeing it.  If release
11527          * fails, don't free the DMA buffer in case FW tries to access it
11528          * later.  If buffer is not owned by firmware, can't release it.
11529          */
11530         if (!pBuffer->owned_by_firmware) {
11531                 status = DDI_SUCCESS;
11532         } else {
11533                 status = mptsas_release_fw_diag_buffer(mpt, pBuffer,
11534                     return_code, MPTSAS_FW_DIAG_TYPE_UNREGISTER);
11535         }
11536 
11537         /*
11538          * At this point, return the current status no matter what happens with
11539          * the DMA buffer.
11540          */
11541         pBuffer->unique_id = MPTSAS_FW_DIAG_INVALID_UID;
11542         if (status == DDI_SUCCESS) {
11543                 if (mptsas_check_dma_handle(pBuffer->buffer_data.handle) !=
11544                     DDI_SUCCESS) {
11545                         mptsas_log(mpt, CE_WARN, "Check of DMA handle failed "
11546                             "in mptsas_diag_unregister.");
11547                         ddi_fm_service_impact(mpt->m_dip,
11548                             DDI_SERVICE_UNAFFECTED);
11549                 }
11550                 mptsas_dma_free(&pBuffer->buffer_data);
11551         }
11552 
11553         return (status);
11554 }
11555 
11556 static int
11557 mptsas_diag_query(mptsas_t *mpt, mptsas_fw_diag_query_t *diag_query,
11558     uint32_t *return_code)
11559 {
11560         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11561         uint8_t                         i;
11562         uint32_t                        unique_id;
11563 
11564         ASSERT(mutex_owned(&mpt->m_mutex));
11565 
11566         unique_id = diag_query->UniqueId;
11567 
11568         /*
11569          * If ID is valid, query on ID.
11570          * If ID is invalid, query on buffer type.
11571          */
11572         if (unique_id == MPTSAS_FW_DIAG_INVALID_UID) {
11573                 i = diag_query->BufferType;
11574                 if (i >= MPI2_DIAG_BUF_TYPE_COUNT) {
11575                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11576                         return (DDI_FAILURE);
11577                 }
11578         } else {
11579                 i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11580                 if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11581                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11582                         return (DDI_FAILURE);
11583                 }
11584         }
11585 
11586         /*
11587          * Fill query structure with the diag buffer info.
11588          */
11589         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11590         diag_query->BufferType = pBuffer->buffer_type;
11591         diag_query->ExtendedType = pBuffer->extended_type;
11592         if (diag_query->BufferType == MPI2_DIAG_BUF_TYPE_TRACE) {
11593                 for (i = 0; i < (sizeof (diag_query->ProductSpecific) / 4);
11594                     i++) {
11595                         diag_query->ProductSpecific[i] =
11596                             pBuffer->product_specific[i];
11597                 }
11598         }
11599         diag_query->TotalBufferSize = pBuffer->buffer_data.size;
11600         diag_query->DriverAddedBufferSize = 0;
11601         diag_query->UniqueId = pBuffer->unique_id;
11602         diag_query->ApplicationFlags = 0;
11603         diag_query->DiagnosticFlags = 0;
11604 
11605         /*
11606          * Set/Clear application flags
11607          */
11608         if (pBuffer->immediate) {
11609                 diag_query->ApplicationFlags &= ~MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11610         } else {
11611                 diag_query->ApplicationFlags |= MPTSAS_FW_DIAG_FLAG_APP_OWNED;
11612         }
11613         if (pBuffer->valid_data || pBuffer->owned_by_firmware) {
11614                 diag_query->ApplicationFlags |=
11615                     MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11616         } else {
11617                 diag_query->ApplicationFlags &=
11618                     ~MPTSAS_FW_DIAG_FLAG_BUFFER_VALID;
11619         }
11620         if (pBuffer->owned_by_firmware) {
11621                 diag_query->ApplicationFlags |=
11622                     MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11623         } else {
11624                 diag_query->ApplicationFlags &=
11625                     ~MPTSAS_FW_DIAG_FLAG_FW_BUFFER_ACCESS;
11626         }
11627 
11628         return (DDI_SUCCESS);
11629 }
11630 
11631 static int
11632 mptsas_diag_read_buffer(mptsas_t *mpt,
11633     mptsas_diag_read_buffer_t *diag_read_buffer, uint8_t *ioctl_buf,
11634     uint32_t *return_code, int ioctl_mode)
11635 {
11636         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11637         uint8_t                         i, *pData;
11638         uint32_t                        unique_id, byte;
11639         int                             status;
11640 
11641         ASSERT(mutex_owned(&mpt->m_mutex));
11642 
11643         unique_id = diag_read_buffer->UniqueId;
11644 
11645         /*
11646          * Get the current buffer and look up the unique ID.  The unique ID
11647          * should be there.
11648          */
11649         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11650         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11651                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11652                 return (DDI_FAILURE);
11653         }
11654 
11655         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11656 
11657         /*
11658          * Make sure requested read is within limits
11659          */
11660         if (diag_read_buffer->StartingOffset + diag_read_buffer->BytesToRead >
11661             pBuffer->buffer_data.size) {
11662                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11663                 return (DDI_FAILURE);
11664         }
11665 
11666         /*
11667          * Copy the requested data from DMA to the diag_read_buffer.  The DMA
11668          * buffer that was allocated is one contiguous buffer.
11669          */
11670         pData = (uint8_t *)(pBuffer->buffer_data.memp +
11671             diag_read_buffer->StartingOffset);
11672         (void) ddi_dma_sync(pBuffer->buffer_data.handle, 0, 0,
11673             DDI_DMA_SYNC_FORCPU);
11674         for (byte = 0; byte < diag_read_buffer->BytesToRead; byte++) {
11675                 if (ddi_copyout(pData + byte, ioctl_buf + byte, 1, ioctl_mode)
11676                     != 0) {
11677                         return (DDI_FAILURE);
11678                 }
11679         }
11680         diag_read_buffer->Status = 0;
11681 
11682         /*
11683          * Set or clear the Force Release flag.
11684          */
11685         if (pBuffer->force_release) {
11686                 diag_read_buffer->Flags |= MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11687         } else {
11688                 diag_read_buffer->Flags &= ~MPTSAS_FW_DIAG_FLAG_FORCE_RELEASE;
11689         }
11690 
11691         /*
11692          * If buffer is to be reregistered, make sure it's not already owned by
11693          * firmware first.
11694          */
11695         status = DDI_SUCCESS;
11696         if (!pBuffer->owned_by_firmware) {
11697                 if (diag_read_buffer->Flags & MPTSAS_FW_DIAG_FLAG_REREGISTER) {
11698                         status = mptsas_post_fw_diag_buffer(mpt, pBuffer,
11699                             return_code);
11700                 }
11701         }
11702 
11703         return (status);
11704 }
11705 
11706 static int
11707 mptsas_diag_release(mptsas_t *mpt, mptsas_fw_diag_release_t *diag_release,
11708     uint32_t *return_code)
11709 {
11710         mptsas_fw_diagnostic_buffer_t   *pBuffer;
11711         uint8_t                         i;
11712         uint32_t                        unique_id;
11713         int                             status;
11714 
11715         ASSERT(mutex_owned(&mpt->m_mutex));
11716 
11717         unique_id = diag_release->UniqueId;
11718 
11719         /*
11720          * Get the current buffer and look up the unique ID.  The unique ID
11721          * should be there.
11722          */
11723         i = mptsas_get_fw_diag_buffer_number(mpt, unique_id);
11724         if (i == MPTSAS_FW_DIAGNOSTIC_UID_NOT_FOUND) {
11725                 *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_UID;
11726                 return (DDI_FAILURE);
11727         }
11728 
11729         pBuffer = &mpt->m_fw_diag_buffer_list[i];
11730 
11731         /*
11732          * If buffer is not owned by firmware, it's already been released.
11733          */
11734         if (!pBuffer->owned_by_firmware) {
11735                 *return_code = MPTSAS_FW_DIAG_ERROR_ALREADY_RELEASED;
11736                 return (DDI_FAILURE);
11737         }
11738 
11739         /*
11740          * Release the buffer.
11741          */
11742         status = mptsas_release_fw_diag_buffer(mpt, pBuffer, return_code,
11743             MPTSAS_FW_DIAG_TYPE_RELEASE);
11744         return (status);
11745 }
11746 
11747 static int
11748 mptsas_do_diag_action(mptsas_t *mpt, uint32_t action, uint8_t *diag_action,
11749     uint32_t length, uint32_t *return_code, int ioctl_mode)
11750 {
11751         mptsas_fw_diag_register_t       diag_register;
11752         mptsas_fw_diag_unregister_t     diag_unregister;
11753         mptsas_fw_diag_query_t          diag_query;
11754         mptsas_diag_read_buffer_t       diag_read_buffer;
11755         mptsas_fw_diag_release_t        diag_release;
11756         int                             status = DDI_SUCCESS;
11757         uint32_t                        original_return_code, read_buf_len;
11758 
11759         ASSERT(mutex_owned(&mpt->m_mutex));
11760 
11761         original_return_code = *return_code;
11762         *return_code = MPTSAS_FW_DIAG_ERROR_SUCCESS;
11763 
11764         switch (action) {
11765                 case MPTSAS_FW_DIAG_TYPE_REGISTER:
11766                         if (!length) {
11767                                 *return_code =
11768                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11769                                 status = DDI_FAILURE;
11770                                 break;
11771                         }
11772                         if (ddi_copyin(diag_action, &diag_register,
11773                             sizeof (diag_register), ioctl_mode) != 0) {
11774                                 return (DDI_FAILURE);
11775                         }
11776                         status = mptsas_diag_register(mpt, &diag_register,
11777                             return_code);
11778                         break;
11779 
11780                 case MPTSAS_FW_DIAG_TYPE_UNREGISTER:
11781                         if (length < sizeof (diag_unregister)) {
11782                                 *return_code =
11783                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11784                                 status = DDI_FAILURE;
11785                                 break;
11786                         }
11787                         if (ddi_copyin(diag_action, &diag_unregister,
11788                             sizeof (diag_unregister), ioctl_mode) != 0) {
11789                                 return (DDI_FAILURE);
11790                         }
11791                         status = mptsas_diag_unregister(mpt, &diag_unregister,
11792                             return_code);
11793                         break;
11794 
11795                 case MPTSAS_FW_DIAG_TYPE_QUERY:
11796                         if (length < sizeof (diag_query)) {
11797                                 *return_code =
11798                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11799                                 status = DDI_FAILURE;
11800                                 break;
11801                         }
11802                         if (ddi_copyin(diag_action, &diag_query,
11803                             sizeof (diag_query), ioctl_mode) != 0) {
11804                                 return (DDI_FAILURE);
11805                         }
11806                         status = mptsas_diag_query(mpt, &diag_query,
11807                             return_code);
11808                         if (status == DDI_SUCCESS) {
11809                                 if (ddi_copyout(&diag_query, diag_action,
11810                                     sizeof (diag_query), ioctl_mode) != 0) {
11811                                         return (DDI_FAILURE);
11812                                 }
11813                         }
11814                         break;
11815 
11816                 case MPTSAS_FW_DIAG_TYPE_READ_BUFFER:
11817                         if (ddi_copyin(diag_action, &diag_read_buffer,
11818                             sizeof (diag_read_buffer) - 4, ioctl_mode) != 0) {
11819                                 return (DDI_FAILURE);
11820                         }
11821                         read_buf_len = sizeof (diag_read_buffer) -
11822                             sizeof (diag_read_buffer.DataBuffer) +
11823                             diag_read_buffer.BytesToRead;
11824                         if (length < read_buf_len) {
11825                                 *return_code =
11826                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11827                                 status = DDI_FAILURE;
11828                                 break;
11829                         }
11830                         status = mptsas_diag_read_buffer(mpt,
11831                             &diag_read_buffer, diag_action +
11832                             sizeof (diag_read_buffer) - 4, return_code,
11833                             ioctl_mode);
11834                         if (status == DDI_SUCCESS) {
11835                                 if (ddi_copyout(&diag_read_buffer, diag_action,
11836                                     sizeof (diag_read_buffer) - 4, ioctl_mode)
11837                                     != 0) {
11838                                         return (DDI_FAILURE);
11839                                 }
11840                         }
11841                         break;
11842 
11843                 case MPTSAS_FW_DIAG_TYPE_RELEASE:
11844                         if (length < sizeof (diag_release)) {
11845                                 *return_code =
11846                                     MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11847                                 status = DDI_FAILURE;
11848                                 break;
11849                         }
11850                         if (ddi_copyin(diag_action, &diag_release,
11851                             sizeof (diag_release), ioctl_mode) != 0) {
11852                                 return (DDI_FAILURE);
11853                         }
11854                         status = mptsas_diag_release(mpt, &diag_release,
11855                             return_code);
11856                         break;
11857 
11858                 default:
11859                         *return_code = MPTSAS_FW_DIAG_ERROR_INVALID_PARAMETER;
11860                         status = DDI_FAILURE;
11861                         break;
11862         }
11863 
11864         if ((status == DDI_FAILURE) &&
11865             (original_return_code == MPTSAS_FW_DIAG_NEW) &&
11866             (*return_code != MPTSAS_FW_DIAG_ERROR_SUCCESS)) {
11867                 status = DDI_SUCCESS;
11868         }
11869 
11870         return (status);
11871 }
11872 
11873 static int
11874 mptsas_diag_action(mptsas_t *mpt, mptsas_diag_action_t *user_data, int mode)
11875 {
11876         int                     status;
11877         mptsas_diag_action_t    driver_data;
11878 
11879         ASSERT(mutex_owned(&mpt->m_mutex));
11880 
11881         /*
11882          * Copy the user data to a driver data buffer.
11883          */
11884         if (ddi_copyin(user_data, &driver_data, sizeof (mptsas_diag_action_t),
11885             mode) == 0) {
11886                 /*
11887                  * Send diag action request if Action is valid
11888                  */
11889                 if (driver_data.Action == MPTSAS_FW_DIAG_TYPE_REGISTER ||
11890                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_UNREGISTER ||
11891                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_QUERY ||
11892                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_READ_BUFFER ||
11893                     driver_data.Action == MPTSAS_FW_DIAG_TYPE_RELEASE) {
11894                         status = mptsas_do_diag_action(mpt, driver_data.Action,
11895                             (void *)(uintptr_t)driver_data.PtrDiagAction,
11896                             driver_data.Length, &driver_data.ReturnCode,
11897                             mode);
11898                         if (status == DDI_SUCCESS) {
11899                                 if (ddi_copyout(&driver_data.ReturnCode,
11900                                     &user_data->ReturnCode,
11901                                     sizeof (user_data->ReturnCode), mode)
11902                                     != 0) {
11903                                         status = EFAULT;
11904                                 } else {
11905                                         status = 0;
11906                                 }
11907                         } else {
11908                                 status = EIO;
11909                         }
11910                 } else {
11911                         status = EINVAL;
11912                 }
11913         } else {
11914                 status = EFAULT;
11915         }
11916 
11917         return (status);
11918 }
11919 
11920 /*
11921  * This routine handles the "event query" ioctl.
11922  */
11923 static int
11924 mptsas_event_query(mptsas_t *mpt, mptsas_event_query_t *data, int mode,
11925     int *rval)
11926 {
11927         int                     status;
11928         mptsas_event_query_t    driverdata;
11929         uint8_t                 i;
11930 
11931         driverdata.Entries = MPTSAS_EVENT_QUEUE_SIZE;
11932 
11933         mutex_enter(&mpt->m_mutex);
11934         for (i = 0; i < 4; i++) {
11935                 driverdata.Types[i] = mpt->m_event_mask[i];
11936         }
11937         mutex_exit(&mpt->m_mutex);
11938 
11939         if (ddi_copyout(&driverdata, data, sizeof (driverdata), mode) != 0) {
11940                 status = EFAULT;
11941         } else {
11942                 *rval = MPTIOCTL_STATUS_GOOD;
11943                 status = 0;
11944         }
11945 
11946         return (status);
11947 }
11948 
11949 /*
11950  * This routine handles the "event enable" ioctl.
11951  */
11952 static int
11953 mptsas_event_enable(mptsas_t *mpt, mptsas_event_enable_t *data, int mode,
11954     int *rval)
11955 {
11956         int                     status;
11957         mptsas_event_enable_t   driverdata;
11958         uint8_t                 i;
11959 
11960         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
11961                 mutex_enter(&mpt->m_mutex);
11962                 for (i = 0; i < 4; i++) {
11963                         mpt->m_event_mask[i] = driverdata.Types[i];
11964                 }
11965                 mutex_exit(&mpt->m_mutex);
11966 
11967                 *rval = MPTIOCTL_STATUS_GOOD;
11968                 status = 0;
11969         } else {
11970                 status = EFAULT;
11971         }
11972         return (status);
11973 }
11974 
11975 /*
11976  * This routine handles the "event report" ioctl.
11977  */
11978 static int
11979 mptsas_event_report(mptsas_t *mpt, mptsas_event_report_t *data, int mode,
11980     int *rval)
11981 {
11982         int                     status;
11983         mptsas_event_report_t   driverdata;
11984 
11985         mutex_enter(&mpt->m_mutex);
11986 
11987         if (ddi_copyin(&data->Size, &driverdata.Size, sizeof (driverdata.Size),
11988             mode) == 0) {
11989                 if (driverdata.Size >= sizeof (mpt->m_events)) {
11990                         if (ddi_copyout(mpt->m_events, data->Events,
11991                             sizeof (mpt->m_events), mode) != 0) {
11992                                 status = EFAULT;
11993                         } else {
11994                                 if (driverdata.Size > sizeof (mpt->m_events)) {
11995                                         driverdata.Size =
11996                                             sizeof (mpt->m_events);
11997                                         if (ddi_copyout(&driverdata.Size,
11998                                             &data->Size,
11999                                             sizeof (driverdata.Size),
12000                                             mode) != 0) {
12001                                                 status = EFAULT;
12002                                         } else {
12003                                                 *rval = MPTIOCTL_STATUS_GOOD;
12004                                                 status = 0;
12005                                         }
12006                                 } else {
12007                                         *rval = MPTIOCTL_STATUS_GOOD;
12008                                         status = 0;
12009                                 }
12010                         }
12011                 } else {
12012                         *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
12013                         status = 0;
12014                 }
12015         } else {
12016                 status = EFAULT;
12017         }
12018 
12019         mutex_exit(&mpt->m_mutex);
12020         return (status);
12021 }
12022 
12023 static void
12024 mptsas_lookup_pci_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
12025 {
12026         int     *reg_data;
12027         uint_t  reglen;
12028 
12029         /*
12030          * Lookup the 'reg' property and extract the other data
12031          */
12032         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
12033             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
12034             DDI_PROP_SUCCESS) {
12035                 /*
12036                  * Extract the PCI data from the 'reg' property first DWORD.
12037                  * The entry looks like the following:
12038                  * First DWORD:
12039                  * Bits 0 - 7 8-bit Register number
12040                  * Bits 8 - 10 3-bit Function number
12041                  * Bits 11 - 15 5-bit Device number
12042                  * Bits 16 - 23 8-bit Bus number
12043                  * Bits 24 - 25 2-bit Address Space type identifier
12044                  *
12045                  */
12046                 adapter_data->PciInformation.u.bits.BusNumber =
12047                     (reg_data[0] & 0x00FF0000) >> 16;
12048                 adapter_data->PciInformation.u.bits.DeviceNumber =
12049                     (reg_data[0] & 0x0000F800) >> 11;
12050                 adapter_data->PciInformation.u.bits.FunctionNumber =
12051                     (reg_data[0] & 0x00000700) >> 8;
12052                 ddi_prop_free((void *)reg_data);
12053         } else {
12054                 /*
12055                  * If we can't determine the PCI data then we fill in FF's for
12056                  * the data to indicate this.
12057                  */
12058                 adapter_data->PCIDeviceHwId = 0xFFFFFFFF;
12059                 adapter_data->MpiPortNumber = 0xFFFFFFFF;
12060                 adapter_data->PciInformation.u.AsDWORD = 0xFFFFFFFF;
12061         }
12062 
12063         /*
12064          * Saved in the mpt->m_fwversion
12065          */
12066         adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
12067 }
12068 
12069 static void
12070 mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
12071 {
12072         char    *driver_verstr = MPTSAS_MOD_STRING;
12073 
12074         mptsas_lookup_pci_data(mpt, adapter_data);
12075         adapter_data->AdapterType = mpt->m_MPI25 ?
12076             MPTIOCTL_ADAPTER_TYPE_SAS3 :
12077             MPTIOCTL_ADAPTER_TYPE_SAS2;
12078         adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
12079         adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
12080         adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
12081         adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
12082         (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
12083         adapter_data->BiosVersion = 0;
12084         (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
12085 }
12086 
12087 static void
12088 mptsas_read_pci_info(mptsas_t *mpt, mptsas_pci_info_t *pci_info)
12089 {
12090         int     *reg_data, i;
12091         uint_t  reglen;
12092 
12093         /*
12094          * Lookup the 'reg' property and extract the other data
12095          */
12096         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, mpt->m_dip,
12097             DDI_PROP_DONTPASS, "reg", &reg_data, &reglen) ==
12098             DDI_PROP_SUCCESS) {
12099                 /*
12100                  * Extract the PCI data from the 'reg' property first DWORD.
12101                  * The entry looks like the following:
12102                  * First DWORD:
12103                  * Bits 8 - 10 3-bit Function number
12104                  * Bits 11 - 15 5-bit Device number
12105                  * Bits 16 - 23 8-bit Bus number
12106                  */
12107                 pci_info->BusNumber = (reg_data[0] & 0x00FF0000) >> 16;
12108                 pci_info->DeviceNumber = (reg_data[0] & 0x0000F800) >> 11;
12109                 pci_info->FunctionNumber = (reg_data[0] & 0x00000700) >> 8;
12110                 ddi_prop_free((void *)reg_data);
12111         } else {
12112                 /*
12113                  * If we can't determine the PCI info then we fill in FF's for
12114                  * the data to indicate this.
12115                  */
12116                 pci_info->BusNumber = 0xFFFFFFFF;
12117                 pci_info->DeviceNumber = 0xFF;
12118                 pci_info->FunctionNumber = 0xFF;
12119         }
12120 
12121         /*
12122          * Now get the interrupt vector and the pci header.  The vector can
12123          * only be 0 right now.  The header is the first 256 bytes of config
12124          * space.
12125          */
12126         pci_info->InterruptVector = 0;
12127         for (i = 0; i < sizeof (pci_info->PciHeader); i++) {
12128                 pci_info->PciHeader[i] = pci_config_get8(mpt->m_config_handle,
12129                     i);
12130         }
12131 }
12132 
12133 static int
12134 mptsas_reg_access(mptsas_t *mpt, mptsas_reg_access_t *data, int mode)
12135 {
12136         int                     status = 0;
12137         mptsas_reg_access_t     driverdata;
12138 
12139         mutex_enter(&mpt->m_mutex);
12140         if (ddi_copyin(data, &driverdata, sizeof (driverdata), mode) == 0) {
12141                 switch (driverdata.Command) {
12142                         /*
12143                          * IO access is not supported.
12144                          */
12145                         case REG_IO_READ:
12146                         case REG_IO_WRITE:
12147                                 mptsas_log(mpt, CE_WARN, "IO access is not "
12148                                     "supported.  Use memory access.");
12149                                 status = EINVAL;
12150                                 break;
12151 
12152                         case REG_MEM_READ:
12153                                 driverdata.RegData = ddi_get32(mpt->m_datap,
12154                                     (uint32_t *)(void *)mpt->m_reg +
12155                                     driverdata.RegOffset);
12156                                 if (ddi_copyout(&driverdata.RegData,
12157                                     &data->RegData,
12158                                     sizeof (driverdata.RegData), mode) != 0) {
12159                                         mptsas_log(mpt, CE_WARN, "Register "
12160                                             "Read Failed");
12161                                         status = EFAULT;
12162                                 }
12163                                 break;
12164 
12165                         case REG_MEM_WRITE:
12166                                 ddi_put32(mpt->m_datap,
12167                                     (uint32_t *)(void *)mpt->m_reg +
12168                                     driverdata.RegOffset,
12169                                     driverdata.RegData);
12170                                 break;
12171 
12172                         default:
12173                                 status = EINVAL;
12174                                 break;
12175                 }
12176         } else {
12177                 status = EFAULT;
12178         }
12179 
12180         mutex_exit(&mpt->m_mutex);
12181         return (status);
12182 }
12183 
12184 static int
12185 led_control(mptsas_t *mpt, intptr_t data, int mode)
12186 {
12187         int ret = 0;
12188         mptsas_led_control_t lc;
12189         mptsas_target_t *ptgt;
12190 
12191         if (ddi_copyin((void *)data, &lc, sizeof (lc), mode) != 0) {
12192                 return (EFAULT);
12193         }
12194 
12195         if ((lc.Command != MPTSAS_LEDCTL_FLAG_SET &&
12196             lc.Command != MPTSAS_LEDCTL_FLAG_GET) ||
12197             lc.Led < MPTSAS_LEDCTL_LED_MIN ||
12198             lc.Led > MPTSAS_LEDCTL_LED_MAX ||
12199             (lc.Command == MPTSAS_LEDCTL_FLAG_SET && lc.LedStatus != 0 &&
12200             lc.LedStatus != 1)) {
12201                 return (EINVAL);
12202         }
12203 
12204         if ((lc.Command == MPTSAS_LEDCTL_FLAG_SET && (mode & FWRITE) == 0) ||
12205             (lc.Command == MPTSAS_LEDCTL_FLAG_GET && (mode & FREAD) == 0))
12206                 return (EACCES);
12207 
12208         /* Locate the target we're interrogating... */
12209         mutex_enter(&mpt->m_mutex);
12210         ptgt = refhash_linear_search(mpt->m_targets,
12211             mptsas_target_eval_slot, &lc);
12212         if (ptgt == NULL) {
12213                 /* We could not find a target for that enclosure/slot. */
12214                 mutex_exit(&mpt->m_mutex);
12215                 return (ENOENT);
12216         }
12217 
12218         if (lc.Command == MPTSAS_LEDCTL_FLAG_SET) {
12219                 /* Update our internal LED state. */
12220                 ptgt->m_led_status &= ~(1 << (lc.Led - 1));
12221                 ptgt->m_led_status |= lc.LedStatus << (lc.Led - 1);
12222 
12223                 /* Flush it to the controller. */
12224                 ret = mptsas_flush_led_status(mpt, ptgt);
12225                 mutex_exit(&mpt->m_mutex);
12226                 return (ret);
12227         }
12228 
12229         /* Return our internal LED state. */
12230         lc.LedStatus = (ptgt->m_led_status >> (lc.Led - 1)) & 1;
12231         mutex_exit(&mpt->m_mutex);
12232 
12233         if (ddi_copyout(&lc, (void *)data, sizeof (lc), mode) != 0) {
12234                 return (EFAULT);
12235         }
12236 
12237         return (0);
12238 }
12239 
12240 static int
12241 get_disk_info(mptsas_t *mpt, intptr_t data, int mode)
12242 {
12243         uint16_t i = 0;
12244         uint16_t count = 0;
12245         int ret = 0;
12246         mptsas_target_t *ptgt;
12247         mptsas_disk_info_t *di;
12248         STRUCT_DECL(mptsas_get_disk_info, gdi);
12249 
12250         if ((mode & FREAD) == 0)
12251                 return (EACCES);
12252 
12253         STRUCT_INIT(gdi, get_udatamodel());
12254 
12255         if (ddi_copyin((void *)data, STRUCT_BUF(gdi), STRUCT_SIZE(gdi),
12256             mode) != 0) {
12257                 return (EFAULT);
12258         }
12259 
12260         /* Find out how many targets there are. */
12261         mutex_enter(&mpt->m_mutex);
12262         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12263             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12264                 count++;
12265         }
12266         mutex_exit(&mpt->m_mutex);
12267 
12268         /*
12269          * If we haven't been asked to copy out information on each target,
12270          * then just return the count.
12271          */
12272         STRUCT_FSET(gdi, DiskCount, count);
12273         if (STRUCT_FGETP(gdi, PtrDiskInfoArray) == NULL)
12274                 goto copy_out;
12275 
12276         /*
12277          * If we haven't been given a large enough buffer to copy out into,
12278          * let the caller know.
12279          */
12280         if (STRUCT_FGET(gdi, DiskInfoArraySize) <
12281             count * sizeof (mptsas_disk_info_t)) {
12282                 ret = ENOSPC;
12283                 goto copy_out;
12284         }
12285 
12286         di = kmem_zalloc(count * sizeof (mptsas_disk_info_t), KM_SLEEP);
12287 
12288         mutex_enter(&mpt->m_mutex);
12289         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12290             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12291                 if (i >= count) {
12292                         /*
12293                          * The number of targets changed while we weren't
12294                          * looking, so give up.
12295                          */
12296                         refhash_rele(mpt->m_targets, ptgt);
12297                         mutex_exit(&mpt->m_mutex);
12298                         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12299                         return (EAGAIN);
12300                 }
12301                 di[i].Instance = mpt->m_instance;
12302                 di[i].Enclosure = ptgt->m_enclosure;
12303                 di[i].Slot = ptgt->m_slot_num;
12304                 di[i].SasAddress = ptgt->m_addr.mta_wwn;
12305                 i++;
12306         }
12307         mutex_exit(&mpt->m_mutex);
12308         STRUCT_FSET(gdi, DiskCount, i);
12309 
12310         /* Copy out the disk information to the caller. */
12311         if (ddi_copyout((void *)di, STRUCT_FGETP(gdi, PtrDiskInfoArray),
12312             i * sizeof (mptsas_disk_info_t), mode) != 0) {
12313                 ret = EFAULT;
12314         }
12315 
12316         kmem_free(di, count * sizeof (mptsas_disk_info_t));
12317 
12318 copy_out:
12319         if (ddi_copyout(STRUCT_BUF(gdi), (void *)data, STRUCT_SIZE(gdi),
12320             mode) != 0) {
12321                 ret = EFAULT;
12322         }
12323 
12324         return (ret);
12325 }
12326 
12327 static int
12328 mptsas_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
12329     int *rval)
12330 {
12331         int                     status = 0;
12332         mptsas_t                *mpt;
12333         mptsas_update_flash_t   flashdata;
12334         mptsas_pass_thru_t      passthru_data;
12335         mptsas_adapter_data_t   adapter_data;
12336         mptsas_pci_info_t       pci_info;
12337         int                     copylen;
12338 
12339         int                     iport_flag = 0;
12340         dev_info_t              *dip = NULL;
12341         mptsas_phymask_t        phymask = 0;
12342         struct devctl_iocdata   *dcp = NULL;
12343         char                    *addr = NULL;
12344         mptsas_target_t         *ptgt = NULL;
12345 
12346         *rval = MPTIOCTL_STATUS_GOOD;
12347         if (secpolicy_sys_config(credp, B_FALSE) != 0) {
12348                 return (EPERM);
12349         }
12350 
12351         mpt = ddi_get_soft_state(mptsas_state, MINOR2INST(getminor(dev)));
12352         if (mpt == NULL) {
12353                 /*
12354                  * Called from iport node, get the states
12355                  */
12356                 iport_flag = 1;
12357                 dip = mptsas_get_dip_from_dev(dev, &phymask);
12358                 if (dip == NULL) {
12359                         return (ENXIO);
12360                 }
12361                 mpt = DIP2MPT(dip);
12362         }
12363         /* Make sure power level is D0 before accessing registers */
12364         mutex_enter(&mpt->m_mutex);
12365         if (mpt->m_options & MPTSAS_OPT_PM) {
12366                 (void) pm_busy_component(mpt->m_dip, 0);
12367                 if (mpt->m_power_level != PM_LEVEL_D0) {
12368                         mutex_exit(&mpt->m_mutex);
12369                         if (pm_raise_power(mpt->m_dip, 0, PM_LEVEL_D0) !=
12370                             DDI_SUCCESS) {
12371                                 mptsas_log(mpt, CE_WARN,
12372                                     "mptsas%d: mptsas_ioctl: Raise power "
12373                                     "request failed.", mpt->m_instance);
12374                                 (void) pm_idle_component(mpt->m_dip, 0);
12375                                 return (ENXIO);
12376                         }
12377                 } else {
12378                         mutex_exit(&mpt->m_mutex);
12379                 }
12380         } else {
12381                 mutex_exit(&mpt->m_mutex);
12382         }
12383 
12384         if (iport_flag) {
12385                 status = scsi_hba_ioctl(dev, cmd, data, mode, credp, rval);
12386                 if (status != 0) {
12387                         goto out;
12388                 }
12389                 /*
12390                  * The following code control the OK2RM LED, it doesn't affect
12391                  * the ioctl return status.
12392                  */
12393                 if ((cmd == DEVCTL_DEVICE_ONLINE) ||
12394                     (cmd == DEVCTL_DEVICE_OFFLINE)) {
12395                         if (ndi_dc_allochdl((void *)data, &dcp) !=
12396                             NDI_SUCCESS) {
12397                                 goto out;
12398                         }
12399                         addr = ndi_dc_getaddr(dcp);
12400                         ptgt = mptsas_addr_to_ptgt(mpt, addr, phymask);
12401                         if (ptgt == NULL) {
12402                                 NDBG14(("mptsas_ioctl led control: tgt %s not "
12403                                     "found", addr));
12404                                 ndi_dc_freehdl(dcp);
12405                                 goto out;
12406                         }
12407                         mutex_enter(&mpt->m_mutex);
12408                         if (cmd == DEVCTL_DEVICE_ONLINE) {
12409                                 ptgt->m_tgt_unconfigured = 0;
12410                         } else if (cmd == DEVCTL_DEVICE_OFFLINE) {
12411                                 ptgt->m_tgt_unconfigured = 1;
12412                         }
12413                         if (cmd == DEVCTL_DEVICE_OFFLINE) {
12414                                 ptgt->m_led_status |=
12415                                     (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12416                         } else {
12417                                 ptgt->m_led_status &=
12418                                     ~(1 << (MPTSAS_LEDCTL_LED_OK2RM - 1));
12419                         }
12420                         (void) mptsas_flush_led_status(mpt, ptgt);
12421                         mutex_exit(&mpt->m_mutex);
12422                         ndi_dc_freehdl(dcp);
12423                 }
12424                 goto out;
12425         }
12426         switch (cmd) {
12427                 case MPTIOCTL_GET_DISK_INFO:
12428                         status = get_disk_info(mpt, data, mode);
12429                         break;
12430                 case MPTIOCTL_LED_CONTROL:
12431                         status = led_control(mpt, data, mode);
12432                         break;
12433                 case MPTIOCTL_UPDATE_FLASH:
12434                         if (ddi_copyin((void *)data, &flashdata,
12435                                 sizeof (struct mptsas_update_flash), mode)) {
12436                                 status = EFAULT;
12437                                 break;
12438                         }
12439 
12440                         mutex_enter(&mpt->m_mutex);
12441                         if (mptsas_update_flash(mpt,
12442                             (caddr_t)(long)flashdata.PtrBuffer,
12443                             flashdata.ImageSize, flashdata.ImageType, mode)) {
12444                                 status = EFAULT;
12445                         }
12446 
12447                         /*
12448                          * Reset the chip to start using the new
12449                          * firmware.  Reset if failed also.
12450                          */
12451                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12452                         if (mptsas_restart_ioc(mpt) == DDI_FAILURE) {
12453                                 status = EFAULT;
12454                         }
12455                         mutex_exit(&mpt->m_mutex);
12456                         break;
12457                 case MPTIOCTL_PASS_THRU:
12458                         /*
12459                          * The user has requested to pass through a command to
12460                          * be executed by the MPT firmware.  Call our routine
12461                          * which does this.  Only allow one passthru IOCTL at
12462                          * one time. Other threads will block on
12463                          * m_passthru_mutex, which is of adaptive variant.
12464                          */
12465                         if (ddi_copyin((void *)data, &passthru_data,
12466                             sizeof (mptsas_pass_thru_t), mode)) {
12467                                 status = EFAULT;
12468                                 break;
12469                         }
12470                         mutex_enter(&mpt->m_passthru_mutex);
12471                         mutex_enter(&mpt->m_mutex);
12472                         status = mptsas_pass_thru(mpt, &passthru_data, mode);
12473                         mutex_exit(&mpt->m_mutex);
12474                         mutex_exit(&mpt->m_passthru_mutex);
12475 
12476                         break;
12477                 case MPTIOCTL_GET_ADAPTER_DATA:
12478                         /*
12479                          * The user has requested to read adapter data.  Call
12480                          * our routine which does this.
12481                          */
12482                         bzero(&adapter_data, sizeof (mptsas_adapter_data_t));
12483                         if (ddi_copyin((void *)data, (void *)&adapter_data,
12484                             sizeof (mptsas_adapter_data_t), mode)) {
12485                                 status = EFAULT;
12486                                 break;
12487                         }
12488                         if (adapter_data.StructureLength >=
12489                             sizeof (mptsas_adapter_data_t)) {
12490                                 adapter_data.StructureLength = (uint32_t)
12491                                     sizeof (mptsas_adapter_data_t);
12492                                 copylen = sizeof (mptsas_adapter_data_t);
12493                                 mutex_enter(&mpt->m_mutex);
12494                                 mptsas_read_adapter_data(mpt, &adapter_data);
12495                                 mutex_exit(&mpt->m_mutex);
12496                         } else {
12497                                 adapter_data.StructureLength = (uint32_t)
12498                                     sizeof (mptsas_adapter_data_t);
12499                                 copylen = sizeof (adapter_data.StructureLength);
12500                                 *rval = MPTIOCTL_STATUS_LEN_TOO_SHORT;
12501                         }
12502                         if (ddi_copyout((void *)(&adapter_data), (void *)data,
12503                             copylen, mode) != 0) {
12504                                 status = EFAULT;
12505                         }
12506                         break;
12507                 case MPTIOCTL_GET_PCI_INFO:
12508                         /*
12509                          * The user has requested to read pci info.  Call
12510                          * our routine which does this.
12511                          */
12512                         bzero(&pci_info, sizeof (mptsas_pci_info_t));
12513                         mutex_enter(&mpt->m_mutex);
12514                         mptsas_read_pci_info(mpt, &pci_info);
12515                         mutex_exit(&mpt->m_mutex);
12516                         if (ddi_copyout((void *)(&pci_info), (void *)data,
12517                             sizeof (mptsas_pci_info_t), mode) != 0) {
12518                                 status = EFAULT;
12519                         }
12520                         break;
12521                 case MPTIOCTL_RESET_ADAPTER:
12522                         mutex_enter(&mpt->m_mutex);
12523                         mpt->m_softstate &= ~MPTSAS_SS_MSG_UNIT_RESET;
12524                         if ((mptsas_restart_ioc(mpt)) == DDI_FAILURE) {
12525                                 mptsas_log(mpt, CE_WARN, "reset adapter IOCTL "
12526                                     "failed");
12527                                 status = EFAULT;
12528                         }
12529                         mutex_exit(&mpt->m_mutex);
12530                         break;
12531                 case MPTIOCTL_DIAG_ACTION:
12532                         /*
12533                          * The user has done a diag buffer action.  Call our
12534                          * routine which does this.  Only allow one diag action
12535                          * at one time.
12536                          */
12537                         mutex_enter(&mpt->m_mutex);
12538                         if (mpt->m_diag_action_in_progress) {
12539                                 mutex_exit(&mpt->m_mutex);
12540                                 return (EBUSY);
12541                         }
12542                         mpt->m_diag_action_in_progress = 1;
12543                         status = mptsas_diag_action(mpt,
12544                             (mptsas_diag_action_t *)data, mode);
12545                         mpt->m_diag_action_in_progress = 0;
12546                         mutex_exit(&mpt->m_mutex);
12547                         break;
12548                 case MPTIOCTL_EVENT_QUERY:
12549                         /*
12550                          * The user has done an event query. Call our routine
12551                          * which does this.
12552                          */
12553                         status = mptsas_event_query(mpt,
12554                             (mptsas_event_query_t *)data, mode, rval);
12555                         break;
12556                 case MPTIOCTL_EVENT_ENABLE:
12557                         /*
12558                          * The user has done an event enable. Call our routine
12559                          * which does this.
12560                          */
12561                         status = mptsas_event_enable(mpt,
12562                             (mptsas_event_enable_t *)data, mode, rval);
12563                         break;
12564                 case MPTIOCTL_EVENT_REPORT:
12565                         /*
12566                          * The user has done an event report. Call our routine
12567                          * which does this.
12568                          */
12569                         status = mptsas_event_report(mpt,
12570                             (mptsas_event_report_t *)data, mode, rval);
12571                         break;
12572                 case MPTIOCTL_REG_ACCESS:
12573                         /*
12574                          * The user has requested register access.  Call our
12575                          * routine which does this.
12576                          */
12577                         status = mptsas_reg_access(mpt,
12578                             (mptsas_reg_access_t *)data, mode);
12579                         break;
12580                 default:
12581                         status = scsi_hba_ioctl(dev, cmd, data, mode, credp,
12582                             rval);
12583                         break;
12584         }
12585 
12586 out:
12587         return (status);
12588 }
12589 
12590 int
12591 mptsas_restart_ioc(mptsas_t *mpt)
12592 {
12593         int             rval = DDI_SUCCESS;
12594         mptsas_target_t *ptgt = NULL;
12595 
12596         ASSERT(mutex_owned(&mpt->m_mutex));
12597 
12598         /*
12599          * Set a flag telling I/O path that we're processing a reset.  This is
12600          * needed because after the reset is complete, the hash table still
12601          * needs to be rebuilt.  If I/Os are started before the hash table is
12602          * rebuilt, I/O errors will occur.  This flag allows I/Os to be marked
12603          * so that they can be retried.
12604          */
12605         mpt->m_in_reset = TRUE;
12606 
12607         /*
12608          * Set all throttles to HOLD
12609          */
12610         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12611             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12612                 mptsas_set_throttle(mpt, ptgt, HOLD_THROTTLE);
12613         }
12614 
12615         /*
12616          * Disable interrupts
12617          */
12618         MPTSAS_DISABLE_INTR(mpt);
12619 
12620         /*
12621          * Abort all commands: outstanding commands, commands in waitq and
12622          * tx_waitq.
12623          */
12624         mptsas_flush_hba(mpt);
12625 
12626         /*
12627          * Reinitialize the chip.
12628          */
12629         if (mptsas_init_chip(mpt, FALSE) == DDI_FAILURE) {
12630                 rval = DDI_FAILURE;
12631         }
12632 
12633         /*
12634          * Enable interrupts again
12635          */
12636         MPTSAS_ENABLE_INTR(mpt);
12637 
12638         /*
12639          * If mptsas_init_chip was successful, update the driver data.
12640          */
12641         if (rval == DDI_SUCCESS) {
12642                 mptsas_update_driver_data(mpt);
12643         }
12644 
12645         /*
12646          * Reset the throttles
12647          */
12648         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
12649             ptgt = refhash_next(mpt->m_targets, ptgt)) {
12650                 mptsas_set_throttle(mpt, ptgt, MAX_THROTTLE);
12651         }
12652 
12653         mptsas_doneq_empty(mpt);
12654         mptsas_restart_hba(mpt);
12655 
12656         if (rval != DDI_SUCCESS) {
12657                 mptsas_fm_ereport(mpt, DDI_FM_DEVICE_NO_RESPONSE);
12658                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_LOST);
12659         }
12660 
12661         /*
12662          * Clear the reset flag so that I/Os can continue.
12663          */
12664         mpt->m_in_reset = FALSE;
12665 
12666         return (rval);
12667 }
12668 
12669 static int
12670 mptsas_init_chip(mptsas_t *mpt, int first_time)
12671 {
12672         ddi_dma_cookie_t        cookie;
12673         uint32_t                i;
12674         int                     rval;
12675 
12676         /*
12677          * Check to see if the firmware image is valid
12678          */
12679         if (ddi_get32(mpt->m_datap, &mpt->m_reg->HostDiagnostic) &
12680             MPI2_DIAG_FLASH_BAD_SIG) {
12681                 mptsas_log(mpt, CE_WARN, "mptsas bad flash signature!");
12682                 goto fail;
12683         }
12684 
12685         /*
12686          * Reset the chip
12687          */
12688         rval = mptsas_ioc_reset(mpt, first_time);
12689         if (rval == MPTSAS_RESET_FAIL) {
12690                 mptsas_log(mpt, CE_WARN, "hard reset failed!");
12691                 goto fail;
12692         }
12693 
12694         if ((rval == MPTSAS_SUCCESS_MUR) && (!first_time)) {
12695                 goto mur;
12696         }
12697         /*
12698          * Setup configuration space
12699          */
12700         if (mptsas_config_space_init(mpt) == FALSE) {
12701                 mptsas_log(mpt, CE_WARN, "mptsas_config_space_init "
12702                     "failed!");
12703                 goto fail;
12704         }
12705 
12706         /*
12707          * IOC facts can change after a diag reset so all buffers that are
12708          * based on these numbers must be de-allocated and re-allocated.  Get
12709          * new IOC facts each time chip is initialized.
12710          */
12711         if (mptsas_ioc_get_facts(mpt) == DDI_FAILURE) {
12712                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_get_facts failed");
12713                 goto fail;
12714         }
12715 
12716         mpt->m_targets = refhash_create(MPTSAS_TARGET_BUCKET_COUNT,
12717             mptsas_target_addr_hash, mptsas_target_addr_cmp,
12718             mptsas_target_free, sizeof (mptsas_target_t),
12719             offsetof(mptsas_target_t, m_link),
12720             offsetof(mptsas_target_t, m_addr), KM_SLEEP);
12721 
12722         if (mptsas_alloc_active_slots(mpt, KM_SLEEP)) {
12723                 goto fail;
12724         }
12725         /*
12726          * Allocate request message frames, reply free queue, reply descriptor
12727          * post queue, and reply message frames using latest IOC facts.
12728          */
12729         if (mptsas_alloc_request_frames(mpt) == DDI_FAILURE) {
12730                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_request_frames failed");
12731                 goto fail;
12732         }
12733         if (mptsas_alloc_free_queue(mpt) == DDI_FAILURE) {
12734                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_free_queue failed!");
12735                 goto fail;
12736         }
12737         if (mptsas_alloc_post_queue(mpt) == DDI_FAILURE) {
12738                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_post_queue failed!");
12739                 goto fail;
12740         }
12741         if (mptsas_alloc_reply_frames(mpt) == DDI_FAILURE) {
12742                 mptsas_log(mpt, CE_WARN, "mptsas_alloc_reply_frames failed!");
12743                 goto fail;
12744         }
12745 
12746 mur:
12747         /*
12748          * Re-Initialize ioc to operational state
12749          */
12750         if (mptsas_ioc_init(mpt) == DDI_FAILURE) {
12751                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_init failed");
12752                 goto fail;
12753         }
12754 
12755         mptsas_alloc_reply_args(mpt);
12756 
12757         /*
12758          * Initialize reply post index.  Reply free index is initialized after
12759          * the next loop.
12760          */
12761         mpt->m_post_index = 0;
12762 
12763         /*
12764          * Initialize the Reply Free Queue with the physical addresses of our
12765          * reply frames.
12766          */
12767         cookie.dmac_address = mpt->m_reply_frame_dma_addr;
12768         for (i = 0; i < mpt->m_max_replies; i++) {
12769                 ddi_put32(mpt->m_acc_free_queue_hdl,
12770                     &((uint32_t *)(void *)mpt->m_free_queue)[i],
12771                     cookie.dmac_address);
12772                 cookie.dmac_address += mpt->m_reply_frame_size;
12773         }
12774         (void) ddi_dma_sync(mpt->m_dma_free_queue_hdl, 0, 0,
12775             DDI_DMA_SYNC_FORDEV);
12776 
12777         /*
12778          * Initialize the reply free index to one past the last frame on the
12779          * queue.  This will signify that the queue is empty to start with.
12780          */
12781         mpt->m_free_index = i;
12782         ddi_put32(mpt->m_datap, &mpt->m_reg->ReplyFreeHostIndex, i);
12783 
12784         /*
12785          * Initialize the reply post queue to 0xFFFFFFFF,0xFFFFFFFF's.
12786          */
12787         for (i = 0; i < mpt->m_post_queue_depth; i++) {
12788                 ddi_put64(mpt->m_acc_post_queue_hdl,
12789                     &((uint64_t *)(void *)mpt->m_post_queue)[i],
12790                     0xFFFFFFFFFFFFFFFF);
12791         }
12792         (void) ddi_dma_sync(mpt->m_dma_post_queue_hdl, 0, 0,
12793             DDI_DMA_SYNC_FORDEV);
12794 
12795         /*
12796          * Enable ports
12797          */
12798         if (mptsas_ioc_enable_port(mpt) == DDI_FAILURE) {
12799                 mptsas_log(mpt, CE_WARN, "mptsas_ioc_enable_port failed");
12800                 goto fail;
12801         }
12802 
12803         /*
12804          * enable events
12805          */
12806         if (mptsas_ioc_enable_event_notification(mpt)) {
12807                 goto fail;
12808         }
12809 
12810         /*
12811          * We need checks in attach and these.
12812          * chip_init is called in mult. places
12813          */
12814 
12815         if ((mptsas_check_dma_handle(mpt->m_dma_req_frame_hdl) !=
12816             DDI_SUCCESS) ||
12817             (mptsas_check_dma_handle(mpt->m_dma_reply_frame_hdl) !=
12818             DDI_SUCCESS) ||
12819             (mptsas_check_dma_handle(mpt->m_dma_free_queue_hdl) !=
12820             DDI_SUCCESS) ||
12821             (mptsas_check_dma_handle(mpt->m_dma_post_queue_hdl) !=
12822             DDI_SUCCESS) ||
12823             (mptsas_check_dma_handle(mpt->m_hshk_dma_hdl) !=
12824             DDI_SUCCESS)) {
12825                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
12826                 goto fail;
12827         }
12828 
12829         /* Check all acc handles */
12830         if ((mptsas_check_acc_handle(mpt->m_datap) != DDI_SUCCESS) ||
12831             (mptsas_check_acc_handle(mpt->m_acc_req_frame_hdl) !=
12832             DDI_SUCCESS) ||
12833             (mptsas_check_acc_handle(mpt->m_acc_reply_frame_hdl) !=
12834             DDI_SUCCESS) ||
12835             (mptsas_check_acc_handle(mpt->m_acc_free_queue_hdl) !=
12836             DDI_SUCCESS) ||
12837             (mptsas_check_acc_handle(mpt->m_acc_post_queue_hdl) !=
12838             DDI_SUCCESS) ||
12839             (mptsas_check_acc_handle(mpt->m_hshk_acc_hdl) !=
12840             DDI_SUCCESS) ||
12841             (mptsas_check_acc_handle(mpt->m_config_handle) !=
12842             DDI_SUCCESS)) {
12843                 ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
12844                 goto fail;
12845         }
12846 
12847         return (DDI_SUCCESS);
12848 
12849 fail:
12850         return (DDI_FAILURE);
12851 }
12852 
12853 static int
12854 mptsas_get_pci_cap(mptsas_t *mpt)
12855 {
12856         ushort_t caps_ptr, cap, cap_count;
12857 
12858         if (mpt->m_config_handle == NULL)
12859                 return (FALSE);
12860         /*
12861          * Check if capabilities list is supported and if so,
12862          * get initial capabilities pointer and clear bits 0,1.
12863          */
12864         if (pci_config_get16(mpt->m_config_handle, PCI_CONF_STAT)
12865             & PCI_STAT_CAP) {
12866                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12867                     PCI_CONF_CAP_PTR), 4);
12868         } else {
12869                 caps_ptr = PCI_CAP_NEXT_PTR_NULL;
12870         }
12871 
12872         /*
12873          * Walk capabilities if supported.
12874          */
12875         for (cap_count = 0; caps_ptr != PCI_CAP_NEXT_PTR_NULL; ) {
12876 
12877                 /*
12878                  * Check that we haven't exceeded the maximum number of
12879                  * capabilities and that the pointer is in a valid range.
12880                  */
12881                 if (++cap_count > 48) {
12882                         mptsas_log(mpt, CE_WARN,
12883                             "too many device capabilities.\n");
12884                         break;
12885                 }
12886                 if (caps_ptr < 64) {
12887                         mptsas_log(mpt, CE_WARN,
12888                             "capabilities pointer 0x%x out of range.\n",
12889                             caps_ptr);
12890                         break;
12891                 }
12892 
12893                 /*
12894                  * Get next capability and check that it is valid.
12895                  * For now, we only support power management.
12896                  */
12897                 cap = pci_config_get8(mpt->m_config_handle, caps_ptr);
12898                 switch (cap) {
12899                         case PCI_CAP_ID_PM:
12900                                 mptsas_log(mpt, CE_NOTE,
12901                                     "?mptsas%d supports power management.\n",
12902                                     mpt->m_instance);
12903                                 mpt->m_options |= MPTSAS_OPT_PM;
12904 
12905                                 /* Save PMCSR offset */
12906                                 mpt->m_pmcsr_offset = caps_ptr + PCI_PMCSR;
12907                                 break;
12908                         /*
12909                          * The following capabilities are valid.  Any others
12910                          * will cause a message to be logged.
12911                          */
12912                         case PCI_CAP_ID_VPD:
12913                         case PCI_CAP_ID_MSI:
12914                         case PCI_CAP_ID_PCIX:
12915                         case PCI_CAP_ID_PCI_E:
12916                         case PCI_CAP_ID_MSI_X:
12917                                 break;
12918                         default:
12919                                 mptsas_log(mpt, CE_NOTE,
12920                                     "?mptsas%d unrecognized capability "
12921                                     "0x%x.\n", mpt->m_instance, cap);
12922                                 break;
12923                 }
12924 
12925                 /*
12926                  * Get next capabilities pointer and clear bits 0,1.
12927                  */
12928                 caps_ptr = P2ALIGN(pci_config_get8(mpt->m_config_handle,
12929                     (caps_ptr + PCI_CAP_NEXT_PTR)), 4);
12930         }
12931         return (TRUE);
12932 }
12933 
12934 static int
12935 mptsas_init_pm(mptsas_t *mpt)
12936 {
12937         char            pmc_name[16];
12938         char            *pmc[] = {
12939                                 NULL,
12940                                 "0=Off (PCI D3 State)",
12941                                 "3=On (PCI D0 State)",
12942                                 NULL
12943                         };
12944         uint16_t        pmcsr_stat;
12945 
12946         if (mptsas_get_pci_cap(mpt) == FALSE) {
12947                 return (DDI_FAILURE);
12948         }
12949         /*
12950          * If PCI's capability does not support PM, then don't need
12951          * to registe the pm-components
12952          */
12953         if (!(mpt->m_options & MPTSAS_OPT_PM))
12954                 return (DDI_SUCCESS);
12955         /*
12956          * If power management is supported by this chip, create
12957          * pm-components property for the power management framework
12958          */
12959         (void) sprintf(pmc_name, "NAME=mptsas%d", mpt->m_instance);
12960         pmc[0] = pmc_name;
12961         if (ddi_prop_update_string_array(DDI_DEV_T_NONE, mpt->m_dip,
12962             "pm-components", pmc, 3) != DDI_PROP_SUCCESS) {
12963                 mpt->m_options &= ~MPTSAS_OPT_PM;
12964                 mptsas_log(mpt, CE_WARN,
12965                     "mptsas%d: pm-component property creation failed.",
12966                     mpt->m_instance);
12967                 return (DDI_FAILURE);
12968         }
12969 
12970         /*
12971          * Power on device.
12972          */
12973         (void) pm_busy_component(mpt->m_dip, 0);
12974         pmcsr_stat = pci_config_get16(mpt->m_config_handle,
12975             mpt->m_pmcsr_offset);
12976         if ((pmcsr_stat & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_D0) {
12977                 mptsas_log(mpt, CE_WARN, "mptsas%d: Power up the device",
12978                     mpt->m_instance);
12979                 pci_config_put16(mpt->m_config_handle, mpt->m_pmcsr_offset,
12980                     PCI_PMCSR_D0);
12981         }
12982         if (pm_power_has_changed(mpt->m_dip, 0, PM_LEVEL_D0) != DDI_SUCCESS) {
12983                 mptsas_log(mpt, CE_WARN, "pm_power_has_changed failed");
12984                 return (DDI_FAILURE);
12985         }
12986         mpt->m_power_level = PM_LEVEL_D0;
12987         /*
12988          * Set pm idle delay.
12989          */
12990         mpt->m_pm_idle_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
12991             mpt->m_dip, 0, "mptsas-pm-idle-delay", MPTSAS_PM_IDLE_TIMEOUT);
12992 
12993         return (DDI_SUCCESS);
12994 }
12995 
12996 static int
12997 mptsas_register_intrs(mptsas_t *mpt)
12998 {
12999         dev_info_t *dip;
13000         int intr_types;
13001 
13002         dip = mpt->m_dip;
13003 
13004         /* Get supported interrupt types */
13005         if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) {
13006                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_supported_types "
13007                     "failed\n");
13008                 return (FALSE);
13009         }
13010 
13011         NDBG6(("ddi_intr_get_supported_types() returned: 0x%x", intr_types));
13012 
13013         /*
13014          * Try MSI, but fall back to FIXED
13015          */
13016         if (mptsas_enable_msi && (intr_types & DDI_INTR_TYPE_MSI)) {
13017                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_MSI) == DDI_SUCCESS) {
13018                         NDBG0(("Using MSI interrupt type"));
13019                         mpt->m_intr_type = DDI_INTR_TYPE_MSI;
13020                         return (TRUE);
13021                 }
13022         }
13023         if (intr_types & DDI_INTR_TYPE_FIXED) {
13024                 if (mptsas_add_intrs(mpt, DDI_INTR_TYPE_FIXED) == DDI_SUCCESS) {
13025                         NDBG0(("Using FIXED interrupt type"));
13026                         mpt->m_intr_type = DDI_INTR_TYPE_FIXED;
13027                         return (TRUE);
13028                 } else {
13029                         NDBG0(("FIXED interrupt registration failed"));
13030                         return (FALSE);
13031                 }
13032         }
13033 
13034         return (FALSE);
13035 }
13036 
13037 static void
13038 mptsas_unregister_intrs(mptsas_t *mpt)
13039 {
13040         mptsas_rem_intrs(mpt);
13041 }
13042 
13043 /*
13044  * mptsas_add_intrs:
13045  *
13046  * Register FIXED or MSI interrupts.
13047  */
13048 static int
13049 mptsas_add_intrs(mptsas_t *mpt, int intr_type)
13050 {
13051         dev_info_t      *dip = mpt->m_dip;
13052         int             avail, actual, count = 0;
13053         int             i, flag, ret;
13054 
13055         NDBG6(("mptsas_add_intrs:interrupt type 0x%x", intr_type));
13056 
13057         /* Get number of interrupts */
13058         ret = ddi_intr_get_nintrs(dip, intr_type, &count);
13059         if ((ret != DDI_SUCCESS) || (count <= 0)) {
13060                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_nintrs() failed, "
13061                     "ret %d count %d\n", ret, count);
13062 
13063                 return (DDI_FAILURE);
13064         }
13065 
13066         /* Get number of available interrupts */
13067         ret = ddi_intr_get_navail(dip, intr_type, &avail);
13068         if ((ret != DDI_SUCCESS) || (avail == 0)) {
13069                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_navail() failed, "
13070                     "ret %d avail %d\n", ret, avail);
13071 
13072                 return (DDI_FAILURE);
13073         }
13074 
13075         if (avail < count) {
13076                 mptsas_log(mpt, CE_NOTE, "ddi_intr_get_nvail returned %d, "
13077                     "navail() returned %d", count, avail);
13078         }
13079 
13080         /* Mpt only have one interrupt routine */
13081         if ((intr_type == DDI_INTR_TYPE_MSI) && (count > 1)) {
13082                 count = 1;
13083         }
13084 
13085         /* Allocate an array of interrupt handles */
13086         mpt->m_intr_size = count * sizeof (ddi_intr_handle_t);
13087         mpt->m_htable = kmem_alloc(mpt->m_intr_size, KM_SLEEP);
13088 
13089         flag = DDI_INTR_ALLOC_NORMAL;
13090 
13091         /* call ddi_intr_alloc() */
13092         ret = ddi_intr_alloc(dip, mpt->m_htable, intr_type, 0,
13093             count, &actual, flag);
13094 
13095         if ((ret != DDI_SUCCESS) || (actual == 0)) {
13096                 mptsas_log(mpt, CE_WARN, "ddi_intr_alloc() failed, ret %d\n",
13097                     ret);
13098                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13099                 return (DDI_FAILURE);
13100         }
13101 
13102         /* use interrupt count returned or abort? */
13103         if (actual < count) {
13104                 mptsas_log(mpt, CE_NOTE, "Requested: %d, Received: %d\n",
13105                     count, actual);
13106         }
13107 
13108         mpt->m_intr_cnt = actual;
13109 
13110         /*
13111          * Get priority for first msi, assume remaining are all the same
13112          */
13113         if ((ret = ddi_intr_get_pri(mpt->m_htable[0],
13114             &mpt->m_intr_pri)) != DDI_SUCCESS) {
13115                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_pri() failed %d\n", ret);
13116 
13117                 /* Free already allocated intr */
13118                 for (i = 0; i < actual; i++) {
13119                         (void) ddi_intr_free(mpt->m_htable[i]);
13120                 }
13121 
13122                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13123                 return (DDI_FAILURE);
13124         }
13125 
13126         /* Test for high level mutex */
13127         if (mpt->m_intr_pri >= ddi_intr_get_hilevel_pri()) {
13128                 mptsas_log(mpt, CE_WARN, "mptsas_add_intrs: "
13129                     "Hi level interrupt not supported\n");
13130 
13131                 /* Free already allocated intr */
13132                 for (i = 0; i < actual; i++) {
13133                         (void) ddi_intr_free(mpt->m_htable[i]);
13134                 }
13135 
13136                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13137                 return (DDI_FAILURE);
13138         }
13139 
13140         /* Call ddi_intr_add_handler() */
13141         for (i = 0; i < actual; i++) {
13142                 if ((ret = ddi_intr_add_handler(mpt->m_htable[i], mptsas_intr,
13143                     (caddr_t)mpt, (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
13144                         mptsas_log(mpt, CE_WARN, "ddi_intr_add_handler() "
13145                             "failed %d\n", ret);
13146 
13147                         /* Free already allocated intr */
13148                         for (i = 0; i < actual; i++) {
13149                                 (void) ddi_intr_free(mpt->m_htable[i]);
13150                         }
13151 
13152                         kmem_free(mpt->m_htable, mpt->m_intr_size);
13153                         return (DDI_FAILURE);
13154                 }
13155         }
13156 
13157         if ((ret = ddi_intr_get_cap(mpt->m_htable[0], &mpt->m_intr_cap))
13158             != DDI_SUCCESS) {
13159                 mptsas_log(mpt, CE_WARN, "ddi_intr_get_cap() failed %d\n", ret);
13160 
13161                 /* Free already allocated intr */
13162                 for (i = 0; i < actual; i++) {
13163                         (void) ddi_intr_free(mpt->m_htable[i]);
13164                 }
13165 
13166                 kmem_free(mpt->m_htable, mpt->m_intr_size);
13167                 return (DDI_FAILURE);
13168         }
13169 
13170         /*
13171          * Enable interrupts
13172          */
13173         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
13174                 /* Call ddi_intr_block_enable() for MSI interrupts */
13175                 (void) ddi_intr_block_enable(mpt->m_htable, mpt->m_intr_cnt);
13176         } else {
13177                 /* Call ddi_intr_enable for MSI or FIXED interrupts */
13178                 for (i = 0; i < mpt->m_intr_cnt; i++) {
13179                         (void) ddi_intr_enable(mpt->m_htable[i]);
13180                 }
13181         }
13182         return (DDI_SUCCESS);
13183 }
13184 
13185 /*
13186  * mptsas_rem_intrs:
13187  *
13188  * Unregister FIXED or MSI interrupts
13189  */
13190 static void
13191 mptsas_rem_intrs(mptsas_t *mpt)
13192 {
13193         int     i;
13194 
13195         NDBG6(("mptsas_rem_intrs"));
13196 
13197         /* Disable all interrupts */
13198         if (mpt->m_intr_cap & DDI_INTR_FLAG_BLOCK) {
13199                 /* Call ddi_intr_block_disable() */
13200                 (void) ddi_intr_block_disable(mpt->m_htable, mpt->m_intr_cnt);
13201         } else {
13202                 for (i = 0; i < mpt->m_intr_cnt; i++) {
13203                         (void) ddi_intr_disable(mpt->m_htable[i]);
13204                 }
13205         }
13206 
13207         /* Call ddi_intr_remove_handler() */
13208         for (i = 0; i < mpt->m_intr_cnt; i++) {
13209                 (void) ddi_intr_remove_handler(mpt->m_htable[i]);
13210                 (void) ddi_intr_free(mpt->m_htable[i]);
13211         }
13212 
13213         kmem_free(mpt->m_htable, mpt->m_intr_size);
13214 }
13215 
13216 /*
13217  * The IO fault service error handling callback function
13218  */
13219 /*ARGSUSED*/
13220 static int
13221 mptsas_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
13222 {
13223         /*
13224          * as the driver can always deal with an error in any dma or
13225          * access handle, we can just return the fme_status value.
13226          */
13227         pci_ereport_post(dip, err, NULL);
13228         return (err->fme_status);
13229 }
13230 
13231 /*
13232  * mptsas_fm_init - initialize fma capabilities and register with IO
13233  *               fault services.
13234  */
13235 static void
13236 mptsas_fm_init(mptsas_t *mpt)
13237 {
13238         /*
13239          * Need to change iblock to priority for new MSI intr
13240          */
13241         ddi_iblock_cookie_t     fm_ibc;
13242 
13243         /* Only register with IO Fault Services if we have some capability */
13244         if (mpt->m_fm_capabilities) {
13245                 /* Adjust access and dma attributes for FMA */
13246                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
13247                 mpt->m_msg_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13248                 mpt->m_io_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
13249 
13250                 /*
13251                  * Register capabilities with IO Fault Services.
13252                  * mpt->m_fm_capabilities will be updated to indicate
13253                  * capabilities actually supported (not requested.)
13254                  */
13255                 ddi_fm_init(mpt->m_dip, &mpt->m_fm_capabilities, &fm_ibc);
13256 
13257                 /*
13258                  * Initialize pci ereport capabilities if ereport
13259                  * capable (should always be.)
13260                  */
13261                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13262                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13263                         pci_ereport_setup(mpt->m_dip);
13264                 }
13265 
13266                 /*
13267                  * Register error callback if error callback capable.
13268                  */
13269                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13270                         ddi_fm_handler_register(mpt->m_dip,
13271                             mptsas_fm_error_cb, (void *) mpt);
13272                 }
13273         }
13274 }
13275 
13276 /*
13277  * mptsas_fm_fini - Releases fma capabilities and un-registers with IO
13278  *               fault services.
13279  *
13280  */
13281 static void
13282 mptsas_fm_fini(mptsas_t *mpt)
13283 {
13284         /* Only unregister FMA capabilities if registered */
13285         if (mpt->m_fm_capabilities) {
13286 
13287                 /*
13288                  * Un-register error callback if error callback capable.
13289                  */
13290 
13291                 if (DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13292                         ddi_fm_handler_unregister(mpt->m_dip);
13293                 }
13294 
13295                 /*
13296                  * Release any resources allocated by pci_ereport_setup()
13297                  */
13298 
13299                 if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities) ||
13300                     DDI_FM_ERRCB_CAP(mpt->m_fm_capabilities)) {
13301                         pci_ereport_teardown(mpt->m_dip);
13302                 }
13303 
13304                 /* Unregister from IO Fault Services */
13305                 ddi_fm_fini(mpt->m_dip);
13306 
13307                 /* Adjust access and dma attributes for FMA */
13308                 mpt->m_reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
13309                 mpt->m_msg_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13310                 mpt->m_io_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
13311 
13312         }
13313 }
13314 
13315 int
13316 mptsas_check_acc_handle(ddi_acc_handle_t handle)
13317 {
13318         ddi_fm_error_t  de;
13319 
13320         if (handle == NULL)
13321                 return (DDI_FAILURE);
13322         ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
13323         return (de.fme_status);
13324 }
13325 
13326 int
13327 mptsas_check_dma_handle(ddi_dma_handle_t handle)
13328 {
13329         ddi_fm_error_t  de;
13330 
13331         if (handle == NULL)
13332                 return (DDI_FAILURE);
13333         ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
13334         return (de.fme_status);
13335 }
13336 
13337 void
13338 mptsas_fm_ereport(mptsas_t *mpt, char *detail)
13339 {
13340         uint64_t        ena;
13341         char            buf[FM_MAX_CLASS];
13342 
13343         (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
13344         ena = fm_ena_generate(0, FM_ENA_FMT1);
13345         if (DDI_FM_EREPORT_CAP(mpt->m_fm_capabilities)) {
13346                 ddi_fm_ereport_post(mpt->m_dip, buf, ena, DDI_NOSLEEP,
13347                     FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
13348         }
13349 }
13350 
13351 static int
13352 mptsas_get_target_device_info(mptsas_t *mpt, uint32_t page_address,
13353     uint16_t *dev_handle, mptsas_target_t **pptgt)
13354 {
13355         int             rval;
13356         uint32_t        dev_info;
13357         uint64_t        sas_wwn;
13358         mptsas_phymask_t phymask;
13359         uint8_t         physport, phynum, config, disk;
13360         uint64_t        devicename;
13361         uint16_t        pdev_hdl;
13362         mptsas_target_t *tmp_tgt = NULL;
13363         uint16_t        bay_num, enclosure, io_flags;
13364 
13365         ASSERT(*pptgt == NULL);
13366 
13367         rval = mptsas_get_sas_device_page0(mpt, page_address, dev_handle,
13368             &sas_wwn, &dev_info, &physport, &phynum, &pdev_hdl,
13369             &bay_num, &enclosure, &io_flags);
13370         if (rval != DDI_SUCCESS) {
13371                 rval = DEV_INFO_FAIL_PAGE0;
13372                 return (rval);
13373         }
13374 
13375         if ((dev_info & (MPI2_SAS_DEVICE_INFO_SSP_TARGET |
13376             MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13377             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) == NULL) {
13378                 rval = DEV_INFO_WRONG_DEVICE_TYPE;
13379                 return (rval);
13380         }
13381 
13382         /*
13383          * Check if the dev handle is for a Phys Disk. If so, set return value
13384          * and exit.  Don't add Phys Disks to hash.
13385          */
13386         for (config = 0; config < mpt->m_num_raid_configs; config++) {
13387                 for (disk = 0; disk < MPTSAS_MAX_DISKS_IN_CONFIG; disk++) {
13388                         if (*dev_handle == mpt->m_raidconfig[config].
13389                             m_physdisk_devhdl[disk]) {
13390                                 rval = DEV_INFO_PHYS_DISK;
13391                                 return (rval);
13392                         }
13393                 }
13394         }
13395 
13396         /*
13397          * Get SATA Device Name from SAS device page0 for
13398          * sata device, if device name doesn't exist, set mta_wwn to
13399          * 0 for direct attached SATA. For the device behind the expander
13400          * we still can use STP address assigned by expander.
13401          */
13402         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
13403             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
13404                 mutex_exit(&mpt->m_mutex);
13405                 /* alloc a tmp_tgt to send the cmd */
13406                 tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target),
13407                     KM_SLEEP);
13408                 tmp_tgt->m_devhdl = *dev_handle;
13409                 tmp_tgt->m_deviceinfo = dev_info;
13410                 tmp_tgt->m_qfull_retries = QFULL_RETRIES;
13411                 tmp_tgt->m_qfull_retry_interval =
13412                     drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
13413                 tmp_tgt->m_t_throttle = MAX_THROTTLE;
13414                 devicename = mptsas_get_sata_guid(mpt, tmp_tgt, 0);
13415                 kmem_free(tmp_tgt, sizeof (struct mptsas_target));
13416                 mutex_enter(&mpt->m_mutex);
13417                 if (devicename != 0 && (((devicename >> 56) & 0xf0) == 0x50)) {
13418                         sas_wwn = devicename;
13419                 } else if (dev_info & MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH) {
13420                         sas_wwn = 0;
13421                 }
13422         }
13423 
13424         phymask = mptsas_physport_to_phymask(mpt, physport);
13425         *pptgt = mptsas_tgt_alloc(mpt, *dev_handle, sas_wwn,
13426             dev_info, phymask, phynum);
13427         if (*pptgt == NULL) {
13428                 mptsas_log(mpt, CE_WARN, "Failed to allocated target"
13429                     "structure!");
13430                 rval = DEV_INFO_FAIL_ALLOC;
13431                 return (rval);
13432         }
13433         (*pptgt)->m_io_flags = io_flags;
13434         (*pptgt)->m_enclosure = enclosure;
13435         (*pptgt)->m_slot_num = bay_num;
13436         return (DEV_INFO_SUCCESS);
13437 }
13438 
13439 uint64_t
13440 mptsas_get_sata_guid(mptsas_t *mpt, mptsas_target_t *ptgt, int lun)
13441 {
13442         uint64_t        sata_guid = 0, *pwwn = NULL;
13443         int             target = ptgt->m_devhdl;
13444         uchar_t         *inq83 = NULL;
13445         int             inq83_len = 0xFF;
13446         uchar_t         *dblk = NULL;
13447         int             inq83_retry = 3;
13448         int             rval = DDI_FAILURE;
13449 
13450         inq83   = kmem_zalloc(inq83_len, KM_SLEEP);
13451 
13452 inq83_retry:
13453         rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
13454             inq83_len, NULL, 1);
13455         if (rval != DDI_SUCCESS) {
13456                 mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
13457                     "0x83 for target:%x, lun:%x failed!", target, lun);
13458                 goto out;
13459         }
13460         /* According to SAT2, the first descriptor is logic unit name */
13461         dblk = &inq83[4];
13462         if ((dblk[1] & 0x30) != 0) {
13463                 mptsas_log(mpt, CE_WARN, "!Descriptor is not lun associated.");
13464                 goto out;
13465         }
13466         pwwn = (uint64_t *)(void *)(&dblk[4]);
13467         if ((dblk[4] & 0xf0) == 0x50) {
13468                 sata_guid = BE_64(*pwwn);
13469                 goto out;
13470         } else if (dblk[4] == 'A') {
13471                 NDBG20(("SATA drive has no NAA format GUID."));
13472                 goto out;
13473         } else {
13474                 /* The data is not ready, wait and retry */
13475                 inq83_retry--;
13476                 if (inq83_retry <= 0) {
13477                         goto out;
13478                 }
13479                 NDBG20(("The GUID is not ready, retry..."));
13480                 delay(1 * drv_usectohz(1000000));
13481                 goto inq83_retry;
13482         }
13483 out:
13484         kmem_free(inq83, inq83_len);
13485         return (sata_guid);
13486 }
13487 
13488 static int
13489 mptsas_inquiry(mptsas_t *mpt, mptsas_target_t *ptgt, int lun, uchar_t page,
13490     unsigned char *buf, int len, int *reallen, uchar_t evpd)
13491 {
13492         uchar_t                 cdb[CDB_GROUP0];
13493         struct scsi_address     ap;
13494         struct buf              *data_bp = NULL;
13495         int                     resid = 0;
13496         int                     ret = DDI_FAILURE;
13497 
13498         ASSERT(len <= 0xffff);
13499 
13500         ap.a_target = MPTSAS_INVALID_DEVHDL;
13501         ap.a_lun = (uchar_t)(lun);
13502         ap.a_hba_tran = mpt->m_tran;
13503 
13504         data_bp = scsi_alloc_consistent_buf(&ap,
13505             (struct buf *)NULL, len, B_READ, NULL_FUNC, NULL);
13506         if (data_bp == NULL) {
13507                 return (ret);
13508         }
13509         bzero(cdb, CDB_GROUP0);
13510         cdb[0] = SCMD_INQUIRY;
13511         cdb[1] = evpd;
13512         cdb[2] = page;
13513         cdb[3] = (len & 0xff00) >> 8;
13514         cdb[4] = (len & 0x00ff);
13515         cdb[5] = 0;
13516 
13517         ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP0, data_bp,
13518             &resid);
13519         if (ret == DDI_SUCCESS) {
13520                 if (reallen) {
13521                         *reallen = len - resid;
13522                 }
13523                 bcopy((caddr_t)data_bp->b_un.b_addr, buf, len);
13524         }
13525         if (data_bp) {
13526                 scsi_free_consistent_buf(data_bp);
13527         }
13528         return (ret);
13529 }
13530 
13531 static int
13532 mptsas_send_scsi_cmd(mptsas_t *mpt, struct scsi_address *ap,
13533     mptsas_target_t *ptgt, uchar_t *cdb, int cdblen, struct buf *data_bp,
13534     int *resid)
13535 {
13536         struct scsi_pkt         *pktp = NULL;
13537         scsi_hba_tran_t         *tran_clone = NULL;
13538         mptsas_tgt_private_t    *tgt_private = NULL;
13539         int                     ret = DDI_FAILURE;
13540 
13541         /*
13542          * scsi_hba_tran_t->tran_tgt_private is used to pass the address
13543          * information to scsi_init_pkt, allocate a scsi_hba_tran structure
13544          * to simulate the cmds from sd
13545          */
13546         tran_clone = kmem_alloc(
13547             sizeof (scsi_hba_tran_t), KM_SLEEP);
13548         if (tran_clone == NULL) {
13549                 goto out;
13550         }
13551         bcopy((caddr_t)mpt->m_tran,
13552             (caddr_t)tran_clone, sizeof (scsi_hba_tran_t));
13553         tgt_private = kmem_alloc(
13554             sizeof (mptsas_tgt_private_t), KM_SLEEP);
13555         if (tgt_private == NULL) {
13556                 goto out;
13557         }
13558         tgt_private->t_lun = ap->a_lun;
13559         tgt_private->t_private = ptgt;
13560         tran_clone->tran_tgt_private = tgt_private;
13561         ap->a_hba_tran = tran_clone;
13562 
13563         pktp = scsi_init_pkt(ap, (struct scsi_pkt *)NULL,
13564             data_bp, cdblen, sizeof (struct scsi_arq_status),
13565             0, PKT_CONSISTENT, NULL, NULL);
13566         if (pktp == NULL) {
13567                 goto out;
13568         }
13569         bcopy(cdb, pktp->pkt_cdbp, cdblen);
13570         pktp->pkt_flags = FLAG_NOPARITY;
13571         if (scsi_poll(pktp) < 0) {
13572                 goto out;
13573         }
13574         if (((struct scsi_status *)pktp->pkt_scbp)->sts_chk) {
13575                 goto out;
13576         }
13577         if (resid != NULL) {
13578                 *resid = pktp->pkt_resid;
13579         }
13580 
13581         ret = DDI_SUCCESS;
13582 out:
13583         if (pktp) {
13584                 scsi_destroy_pkt(pktp);
13585         }
13586         if (tran_clone) {
13587                 kmem_free(tran_clone, sizeof (scsi_hba_tran_t));
13588         }
13589         if (tgt_private) {
13590                 kmem_free(tgt_private, sizeof (mptsas_tgt_private_t));
13591         }
13592         return (ret);
13593 }
13594 static int
13595 mptsas_parse_address(char *name, uint64_t *wwid, uint8_t *phy, int *lun)
13596 {
13597         char    *cp = NULL;
13598         char    *ptr = NULL;
13599         size_t  s = 0;
13600         char    *wwid_str = NULL;
13601         char    *lun_str = NULL;
13602         long    lunnum;
13603         long    phyid = -1;
13604         int     rc = DDI_FAILURE;
13605 
13606         ptr = name;
13607         ASSERT(ptr[0] == 'w' || ptr[0] == 'p');
13608         ptr++;
13609         if ((cp = strchr(ptr, ',')) == NULL) {
13610                 return (DDI_FAILURE);
13611         }
13612 
13613         wwid_str = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13614         s = (uintptr_t)cp - (uintptr_t)ptr;
13615 
13616         bcopy(ptr, wwid_str, s);
13617         wwid_str[s] = '\0';
13618 
13619         ptr = ++cp;
13620 
13621         if ((cp = strchr(ptr, '\0')) == NULL) {
13622                 goto out;
13623         }
13624         lun_str =  kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13625         s = (uintptr_t)cp - (uintptr_t)ptr;
13626 
13627         bcopy(ptr, lun_str, s);
13628         lun_str[s] = '\0';
13629 
13630         if (name[0] == 'p') {
13631                 rc = ddi_strtol(wwid_str, NULL, 0x10, &phyid);
13632         } else {
13633                 rc = scsi_wwnstr_to_wwn(wwid_str, wwid);
13634         }
13635         if (rc != DDI_SUCCESS)
13636                 goto out;
13637 
13638         if (phyid != -1) {
13639                 ASSERT(phyid < MPTSAS_MAX_PHYS);
13640                 *phy = (uint8_t)phyid;
13641         }
13642         rc = ddi_strtol(lun_str, NULL, 0x10, &lunnum);
13643         if (rc != 0)
13644                 goto out;
13645 
13646         *lun = (int)lunnum;
13647         rc = DDI_SUCCESS;
13648 out:
13649         if (wwid_str)
13650                 kmem_free(wwid_str, SCSI_MAXNAMELEN);
13651         if (lun_str)
13652                 kmem_free(lun_str, SCSI_MAXNAMELEN);
13653 
13654         return (rc);
13655 }
13656 
13657 /*
13658  * mptsas_parse_smp_name() is to parse sas wwn string
13659  * which format is "wWWN"
13660  */
13661 static int
13662 mptsas_parse_smp_name(char *name, uint64_t *wwn)
13663 {
13664         char    *ptr = name;
13665 
13666         if (*ptr != 'w') {
13667                 return (DDI_FAILURE);
13668         }
13669 
13670         ptr++;
13671         if (scsi_wwnstr_to_wwn(ptr, wwn)) {
13672                 return (DDI_FAILURE);
13673         }
13674         return (DDI_SUCCESS);
13675 }
13676 
13677 static int
13678 mptsas_bus_config(dev_info_t *pdip, uint_t flag,
13679     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
13680 {
13681         int             ret = NDI_FAILURE;
13682         int             circ = 0;
13683         int             circ1 = 0;
13684         mptsas_t        *mpt;
13685         char            *ptr = NULL;
13686         char            *devnm = NULL;
13687         uint64_t        wwid = 0;
13688         uint8_t         phy = 0xFF;
13689         int             lun = 0;
13690         uint_t          mflags = flag;
13691         int             bconfig = TRUE;
13692 
13693         if (scsi_hba_iport_unit_address(pdip) == 0) {
13694                 return (DDI_FAILURE);
13695         }
13696 
13697         mpt = DIP2MPT(pdip);
13698         if (!mpt) {
13699                 return (DDI_FAILURE);
13700         }
13701         /*
13702          * Hold the nexus across the bus_config
13703          */
13704         ndi_devi_enter(scsi_vhci_dip, &circ);
13705         ndi_devi_enter(pdip, &circ1);
13706         switch (op) {
13707         case BUS_CONFIG_ONE:
13708                 /* parse wwid/target name out of name given */
13709                 if ((ptr = strchr((char *)arg, '@')) == NULL) {
13710                         ret = NDI_FAILURE;
13711                         break;
13712                 }
13713                 ptr++;
13714                 if (strncmp((char *)arg, "smp", 3) == 0) {
13715                         /*
13716                          * This is a SMP target device
13717                          */
13718                         ret = mptsas_parse_smp_name(ptr, &wwid);
13719                         if (ret != DDI_SUCCESS) {
13720                                 ret = NDI_FAILURE;
13721                                 break;
13722                         }
13723                         ret = mptsas_config_smp(pdip, wwid, childp);
13724                 } else if ((ptr[0] == 'w') || (ptr[0] == 'p')) {
13725                         /*
13726                          * OBP could pass down a non-canonical form
13727                          * bootpath without LUN part when LUN is 0.
13728                          * So driver need adjust the string.
13729                          */
13730                         if (strchr(ptr, ',') == NULL) {
13731                                 devnm = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
13732                                 (void) sprintf(devnm, "%s,0", (char *)arg);
13733                                 ptr = strchr(devnm, '@');
13734                                 ptr++;
13735                         }
13736 
13737                         /*
13738                          * The device path is wWWID format and the device
13739                          * is not SMP target device.
13740                          */
13741                         ret = mptsas_parse_address(ptr, &wwid, &phy, &lun);
13742                         if (ret != DDI_SUCCESS) {
13743                                 ret = NDI_FAILURE;
13744                                 break;
13745                         }
13746                         *childp = NULL;
13747                         if (ptr[0] == 'w') {
13748                                 ret = mptsas_config_one_addr(pdip, wwid,
13749                                     lun, childp);
13750                         } else if (ptr[0] == 'p') {
13751                                 ret = mptsas_config_one_phy(pdip, phy, lun,
13752                                     childp);
13753                         }
13754 
13755                         /*
13756                          * If this is CD/DVD device in OBP path, the
13757                          * ndi_busop_bus_config can be skipped as config one
13758                          * operation is done above.
13759                          */
13760                         if ((ret == NDI_SUCCESS) && (*childp != NULL) &&
13761                             (strcmp(ddi_node_name(*childp), "cdrom") == 0) &&
13762                             (strncmp((char *)arg, "disk", 4) == 0)) {
13763                                 bconfig = FALSE;
13764                                 ndi_hold_devi(*childp);
13765                         }
13766                 } else {
13767                         ret = NDI_FAILURE;
13768                         break;
13769                 }
13770 
13771                 /*
13772                  * DDI group instructed us to use this flag.
13773                  */
13774                 mflags |= NDI_MDI_FALLBACK;
13775                 break;
13776         case BUS_CONFIG_DRIVER:
13777         case BUS_CONFIG_ALL:
13778                 mptsas_config_all(pdip);
13779                 ret = NDI_SUCCESS;
13780                 break;
13781         }
13782 
13783         if ((ret == NDI_SUCCESS) && bconfig) {
13784                 ret = ndi_busop_bus_config(pdip, mflags, op,
13785                     (devnm == NULL) ? arg : devnm, childp, 0);
13786         }
13787 
13788         ndi_devi_exit(pdip, circ1);
13789         ndi_devi_exit(scsi_vhci_dip, circ);
13790         if (devnm != NULL)
13791                 kmem_free(devnm, SCSI_MAXNAMELEN);
13792         return (ret);
13793 }
13794 
13795 static int
13796 mptsas_probe_lun(dev_info_t *pdip, int lun, dev_info_t **dip,
13797     mptsas_target_t *ptgt)
13798 {
13799         int                     rval = DDI_FAILURE;
13800         struct scsi_inquiry     *sd_inq = NULL;
13801         mptsas_t                *mpt = DIP2MPT(pdip);
13802 
13803         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
13804 
13805         rval = mptsas_inquiry(mpt, ptgt, lun, 0, (uchar_t *)sd_inq,
13806             SUN_INQSIZE, 0, (uchar_t)0);
13807 
13808         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
13809                 rval = mptsas_create_lun(pdip, sd_inq, dip, ptgt, lun);
13810         } else {
13811                 rval = DDI_FAILURE;
13812         }
13813 
13814         kmem_free(sd_inq, SUN_INQSIZE);
13815         return (rval);
13816 }
13817 
13818 static int
13819 mptsas_config_one_addr(dev_info_t *pdip, uint64_t sasaddr, int lun,
13820     dev_info_t **lundip)
13821 {
13822         int             rval;
13823         mptsas_t                *mpt = DIP2MPT(pdip);
13824         int             phymask;
13825         mptsas_target_t *ptgt = NULL;
13826 
13827         /*
13828          * Get the physical port associated to the iport
13829          */
13830         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13831             "phymask", 0);
13832 
13833         ptgt = mptsas_wwid_to_ptgt(mpt, phymask, sasaddr);
13834         if (ptgt == NULL) {
13835                 /*
13836                  * didn't match any device by searching
13837                  */
13838                 return (DDI_FAILURE);
13839         }
13840         /*
13841          * If the LUN already exists and the status is online,
13842          * we just return the pointer to dev_info_t directly.
13843          * For the mdi_pathinfo node, we'll handle it in
13844          * mptsas_create_virt_lun()
13845          * TODO should be also in mptsas_handle_dr
13846          */
13847 
13848         *lundip = mptsas_find_child_addr(pdip, sasaddr, lun);
13849         if (*lundip != NULL) {
13850                 /*
13851                  * TODO Another senario is, we hotplug the same disk
13852                  * on the same slot, the devhdl changed, is this
13853                  * possible?
13854                  * tgt_private->t_private != ptgt
13855                  */
13856                 if (sasaddr != ptgt->m_addr.mta_wwn) {
13857                         /*
13858                          * The device has changed although the devhdl is the
13859                          * same (Enclosure mapping mode, change drive on the
13860                          * same slot)
13861                          */
13862                         return (DDI_FAILURE);
13863                 }
13864                 return (DDI_SUCCESS);
13865         }
13866 
13867         if (phymask == 0) {
13868                 /*
13869                  * Configure IR volume
13870                  */
13871                 rval =  mptsas_config_raid(pdip, ptgt->m_devhdl, lundip);
13872                 return (rval);
13873         }
13874         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13875 
13876         return (rval);
13877 }
13878 
13879 static int
13880 mptsas_config_one_phy(dev_info_t *pdip, uint8_t phy, int lun,
13881     dev_info_t **lundip)
13882 {
13883         int             rval;
13884         mptsas_t        *mpt = DIP2MPT(pdip);
13885         mptsas_phymask_t phymask;
13886         mptsas_target_t *ptgt = NULL;
13887 
13888         /*
13889          * Get the physical port associated to the iport
13890          */
13891         phymask = (mptsas_phymask_t)ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
13892             "phymask", 0);
13893 
13894         ptgt = mptsas_phy_to_tgt(mpt, phymask, phy);
13895         if (ptgt == NULL) {
13896                 /*
13897                  * didn't match any device by searching
13898                  */
13899                 return (DDI_FAILURE);
13900         }
13901 
13902         /*
13903          * If the LUN already exists and the status is online,
13904          * we just return the pointer to dev_info_t directly.
13905          * For the mdi_pathinfo node, we'll handle it in
13906          * mptsas_create_virt_lun().
13907          */
13908 
13909         *lundip = mptsas_find_child_phy(pdip, phy);
13910         if (*lundip != NULL) {
13911                 return (DDI_SUCCESS);
13912         }
13913 
13914         rval = mptsas_probe_lun(pdip, lun, lundip, ptgt);
13915 
13916         return (rval);
13917 }
13918 
13919 static int
13920 mptsas_retrieve_lundata(int lun_cnt, uint8_t *buf, uint16_t *lun_num,
13921     uint8_t *lun_addr_type)
13922 {
13923         uint32_t        lun_idx = 0;
13924 
13925         ASSERT(lun_num != NULL);
13926         ASSERT(lun_addr_type != NULL);
13927 
13928         lun_idx = (lun_cnt + 1) * MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
13929         /* determine report luns addressing type */
13930         switch (buf[lun_idx] & MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) {
13931                 /*
13932                  * Vendors in the field have been found to be concatenating
13933                  * bus/target/lun to equal the complete lun value instead
13934                  * of switching to flat space addressing
13935                  */
13936                 /* 00b - peripheral device addressing method */
13937         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_PERIPHERAL:
13938                 /* FALLTHRU */
13939                 /* 10b - logical unit addressing method */
13940         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT:
13941                 /* FALLTHRU */
13942                 /* 01b - flat space addressing method */
13943         case MPTSAS_SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE:
13944                 /* byte0 bit0-5=msb lun byte1 bit0-7=lsb lun */
13945                 *lun_addr_type = (buf[lun_idx] &
13946                     MPTSAS_SCSI_REPORTLUNS_ADDRESS_MASK) >> 6;
13947                 *lun_num = (buf[lun_idx] & 0x3F) << 8;
13948                 *lun_num |= buf[lun_idx + 1];
13949                 return (DDI_SUCCESS);
13950         default:
13951                 return (DDI_FAILURE);
13952         }
13953 }
13954 
13955 static int
13956 mptsas_config_luns(dev_info_t *pdip, mptsas_target_t *ptgt)
13957 {
13958         struct buf              *repluns_bp = NULL;
13959         struct scsi_address     ap;
13960         uchar_t                 cdb[CDB_GROUP5];
13961         int                     ret = DDI_FAILURE;
13962         int                     retry = 0;
13963         int                     lun_list_len = 0;
13964         uint16_t                lun_num = 0;
13965         uint8_t                 lun_addr_type = 0;
13966         uint32_t                lun_cnt = 0;
13967         uint32_t                lun_total = 0;
13968         dev_info_t              *cdip = NULL;
13969         uint16_t                *saved_repluns = NULL;
13970         char                    *buffer = NULL;
13971         int                     buf_len = 128;
13972         mptsas_t                *mpt = DIP2MPT(pdip);
13973         uint64_t                sas_wwn = 0;
13974         uint8_t                 phy = 0xFF;
13975         uint32_t                dev_info = 0;
13976 
13977         mutex_enter(&mpt->m_mutex);
13978         sas_wwn = ptgt->m_addr.mta_wwn;
13979         phy = ptgt->m_phynum;
13980         dev_info = ptgt->m_deviceinfo;
13981         mutex_exit(&mpt->m_mutex);
13982 
13983         if (sas_wwn == 0) {
13984                 /*
13985                  * It's a SATA without Device Name
13986                  * So don't try multi-LUNs
13987                  */
13988                 if (mptsas_find_child_phy(pdip, phy)) {
13989                         return (DDI_SUCCESS);
13990                 } else {
13991                         /*
13992                          * need configure and create node
13993                          */
13994                         return (DDI_FAILURE);
13995                 }
13996         }
13997 
13998         /*
13999          * WWN (SAS address or Device Name exist)
14000          */
14001         if (dev_info & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
14002             MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
14003                 /*
14004                  * SATA device with Device Name
14005                  * So don't try multi-LUNs
14006                  */
14007                 if (mptsas_find_child_addr(pdip, sas_wwn, 0)) {
14008                         return (DDI_SUCCESS);
14009                 } else {
14010                         return (DDI_FAILURE);
14011                 }
14012         }
14013 
14014         do {
14015                 ap.a_target = MPTSAS_INVALID_DEVHDL;
14016                 ap.a_lun = 0;
14017                 ap.a_hba_tran = mpt->m_tran;
14018                 repluns_bp = scsi_alloc_consistent_buf(&ap,
14019                     (struct buf *)NULL, buf_len, B_READ, NULL_FUNC, NULL);
14020                 if (repluns_bp == NULL) {
14021                         retry++;
14022                         continue;
14023                 }
14024                 bzero(cdb, CDB_GROUP5);
14025                 cdb[0] = SCMD_REPORT_LUNS;
14026                 cdb[6] = (buf_len & 0xff000000) >> 24;
14027                 cdb[7] = (buf_len & 0x00ff0000) >> 16;
14028                 cdb[8] = (buf_len & 0x0000ff00) >> 8;
14029                 cdb[9] = (buf_len & 0x000000ff);
14030 
14031                 ret = mptsas_send_scsi_cmd(mpt, &ap, ptgt, &cdb[0], CDB_GROUP5,
14032                     repluns_bp, NULL);
14033                 if (ret != DDI_SUCCESS) {
14034                         scsi_free_consistent_buf(repluns_bp);
14035                         retry++;
14036                         continue;
14037                 }
14038                 lun_list_len = BE_32(*(int *)((void *)(
14039                     repluns_bp->b_un.b_addr)));
14040                 if (buf_len >= lun_list_len + 8) {
14041                         ret = DDI_SUCCESS;
14042                         break;
14043                 }
14044                 scsi_free_consistent_buf(repluns_bp);
14045                 buf_len = lun_list_len + 8;
14046 
14047         } while (retry < 3);
14048 
14049         if (ret != DDI_SUCCESS)
14050                 return (ret);
14051         buffer = (char *)repluns_bp->b_un.b_addr;
14052         /*
14053          * find out the number of luns returned by the SCSI ReportLun call
14054          * and allocate buffer space
14055          */
14056         lun_total = lun_list_len / MPTSAS_SCSI_REPORTLUNS_ADDRESS_SIZE;
14057         saved_repluns = kmem_zalloc(sizeof (uint16_t) * lun_total, KM_SLEEP);
14058         if (saved_repluns == NULL) {
14059                 scsi_free_consistent_buf(repluns_bp);
14060                 return (DDI_FAILURE);
14061         }
14062         for (lun_cnt = 0; lun_cnt < lun_total; lun_cnt++) {
14063                 if (mptsas_retrieve_lundata(lun_cnt, (uint8_t *)(buffer),
14064                     &lun_num, &lun_addr_type) != DDI_SUCCESS) {
14065                         continue;
14066                 }
14067                 saved_repluns[lun_cnt] = lun_num;
14068                 if (cdip = mptsas_find_child_addr(pdip, sas_wwn, lun_num))
14069                         ret = DDI_SUCCESS;
14070                 else
14071                         ret = mptsas_probe_lun(pdip, lun_num, &cdip,
14072                             ptgt);
14073                 if ((ret == DDI_SUCCESS) && (cdip != NULL)) {
14074                         (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip,
14075                             MPTSAS_DEV_GONE);
14076                 }
14077         }
14078         mptsas_offline_missed_luns(pdip, saved_repluns, lun_total, ptgt);
14079         kmem_free(saved_repluns, sizeof (uint16_t) * lun_total);
14080         scsi_free_consistent_buf(repluns_bp);
14081         return (DDI_SUCCESS);
14082 }
14083 
14084 static int
14085 mptsas_config_raid(dev_info_t *pdip, uint16_t target, dev_info_t **dip)
14086 {
14087         int                     rval = DDI_FAILURE;
14088         struct scsi_inquiry     *sd_inq = NULL;
14089         mptsas_t                *mpt = DIP2MPT(pdip);
14090         mptsas_target_t         *ptgt = NULL;
14091 
14092         mutex_enter(&mpt->m_mutex);
14093         ptgt = refhash_linear_search(mpt->m_targets,
14094             mptsas_target_eval_devhdl, &target);
14095         mutex_exit(&mpt->m_mutex);
14096         if (ptgt == NULL) {
14097                 mptsas_log(mpt, CE_WARN, "Volume with VolDevHandle of 0x%x "
14098                     "not found.", target);
14099                 return (rval);
14100         }
14101 
14102         sd_inq = (struct scsi_inquiry *)kmem_alloc(SUN_INQSIZE, KM_SLEEP);
14103         rval = mptsas_inquiry(mpt, ptgt, 0, 0, (uchar_t *)sd_inq,
14104             SUN_INQSIZE, 0, (uchar_t)0);
14105 
14106         if ((rval == DDI_SUCCESS) && MPTSAS_VALID_LUN(sd_inq)) {
14107                 rval = mptsas_create_phys_lun(pdip, sd_inq, NULL, dip, ptgt,
14108                     0);
14109         } else {
14110                 rval = DDI_FAILURE;
14111         }
14112 
14113         kmem_free(sd_inq, SUN_INQSIZE);
14114         return (rval);
14115 }
14116 
14117 /*
14118  * configure all RAID volumes for virtual iport
14119  */
14120 static void
14121 mptsas_config_all_viport(dev_info_t *pdip)
14122 {
14123         mptsas_t        *mpt = DIP2MPT(pdip);
14124         int             config, vol;
14125         int             target;
14126         dev_info_t      *lundip = NULL;
14127 
14128         /*
14129          * Get latest RAID info and search for any Volume DevHandles.  If any
14130          * are found, configure the volume.
14131          */
14132         mutex_enter(&mpt->m_mutex);
14133         for (config = 0; config < mpt->m_num_raid_configs; config++) {
14134                 for (vol = 0; vol < MPTSAS_MAX_RAIDVOLS; vol++) {
14135                         if (mpt->m_raidconfig[config].m_raidvol[vol].m_israid
14136                             == 1) {
14137                                 target = mpt->m_raidconfig[config].
14138                                     m_raidvol[vol].m_raidhandle;
14139                                 mutex_exit(&mpt->m_mutex);
14140                                 (void) mptsas_config_raid(pdip, target,
14141                                     &lundip);
14142                                 mutex_enter(&mpt->m_mutex);
14143                         }
14144                 }
14145         }
14146         mutex_exit(&mpt->m_mutex);
14147 }
14148 
14149 static void
14150 mptsas_offline_missed_luns(dev_info_t *pdip, uint16_t *repluns,
14151     int lun_cnt, mptsas_target_t *ptgt)
14152 {
14153         dev_info_t      *child = NULL, *savechild = NULL;
14154         mdi_pathinfo_t  *pip = NULL, *savepip = NULL;
14155         uint64_t        sas_wwn, wwid;
14156         uint8_t         phy;
14157         int             lun;
14158         int             i;
14159         int             find;
14160         char            *addr;
14161         char            *nodename;
14162         mptsas_t        *mpt = DIP2MPT(pdip);
14163 
14164         mutex_enter(&mpt->m_mutex);
14165         wwid = ptgt->m_addr.mta_wwn;
14166         mutex_exit(&mpt->m_mutex);
14167 
14168         child = ddi_get_child(pdip);
14169         while (child) {
14170                 find = 0;
14171                 savechild = child;
14172                 child = ddi_get_next_sibling(child);
14173 
14174                 nodename = ddi_node_name(savechild);
14175                 if (strcmp(nodename, "smp") == 0) {
14176                         continue;
14177                 }
14178 
14179                 addr = ddi_get_name_addr(savechild);
14180                 if (addr == NULL) {
14181                         continue;
14182                 }
14183 
14184                 if (mptsas_parse_address(addr, &sas_wwn, &phy, &lun) !=
14185                     DDI_SUCCESS) {
14186                         continue;
14187                 }
14188 
14189                 if (wwid == sas_wwn) {
14190                         for (i = 0; i < lun_cnt; i++) {
14191                                 if (repluns[i] == lun) {
14192                                         find = 1;
14193                                         break;
14194                                 }
14195                         }
14196                 } else {
14197                         continue;
14198                 }
14199                 if (find == 0) {
14200                         /*
14201                          * The lun has not been there already
14202                          */
14203                         (void) mptsas_offline_lun(pdip, savechild, NULL,
14204                             NDI_DEVI_REMOVE);
14205                 }
14206         }
14207 
14208         pip = mdi_get_next_client_path(pdip, NULL);
14209         while (pip) {
14210                 find = 0;
14211                 savepip = pip;
14212                 addr = MDI_PI(pip)->pi_addr;
14213 
14214                 pip = mdi_get_next_client_path(pdip, pip);
14215 
14216                 if (addr == NULL) {
14217                         continue;
14218                 }
14219 
14220                 if (mptsas_parse_address(addr, &sas_wwn, &phy,
14221                     &lun) != DDI_SUCCESS) {
14222                         continue;
14223                 }
14224 
14225                 if (sas_wwn == wwid) {
14226                         for (i = 0; i < lun_cnt; i++) {
14227                                 if (repluns[i] == lun) {
14228                                         find = 1;
14229                                         break;
14230                                 }
14231                         }
14232                 } else {
14233                         continue;
14234                 }
14235 
14236                 if (find == 0) {
14237                         /*
14238                          * The lun has not been there already
14239                          */
14240                         (void) mptsas_offline_lun(pdip, NULL, savepip,
14241                             NDI_DEVI_REMOVE);
14242                 }
14243         }
14244 }
14245 
14246 void
14247 mptsas_update_hashtab(struct mptsas *mpt)
14248 {
14249         uint32_t        page_address;
14250         int             rval = 0;
14251         uint16_t        dev_handle;
14252         mptsas_target_t *ptgt = NULL;
14253         mptsas_smp_t    smp_node;
14254 
14255         /*
14256          * Get latest RAID info.
14257          */
14258         (void) mptsas_get_raid_info(mpt);
14259 
14260         dev_handle = mpt->m_smp_devhdl;
14261         for (; mpt->m_done_traverse_smp == 0; ) {
14262                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
14263                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)dev_handle;
14264                 if (mptsas_get_sas_expander_page0(mpt, page_address, &smp_node)
14265                     != DDI_SUCCESS) {
14266                         break;
14267                 }
14268                 mpt->m_smp_devhdl = dev_handle = smp_node.m_devhdl;
14269                 (void) mptsas_smp_alloc(mpt, &smp_node);
14270         }
14271 
14272         /*
14273          * Config target devices
14274          */
14275         dev_handle = mpt->m_dev_handle;
14276 
14277         /*
14278          * Do loop to get sas device page 0 by GetNextHandle till the
14279          * the last handle. If the sas device is a SATA/SSP target,
14280          * we try to config it.
14281          */
14282         for (; mpt->m_done_traverse_dev == 0; ) {
14283                 ptgt = NULL;
14284                 page_address =
14285                     (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
14286                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
14287                     (uint32_t)dev_handle;
14288                 rval = mptsas_get_target_device_info(mpt, page_address,
14289                     &dev_handle, &ptgt);
14290                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
14291                     (rval == DEV_INFO_FAIL_ALLOC)) {
14292                         break;
14293                 }
14294 
14295                 mpt->m_dev_handle = dev_handle;
14296         }
14297 
14298 }
14299 
14300 void
14301 mptsas_update_driver_data(struct mptsas *mpt)
14302 {
14303         mptsas_target_t *tp;
14304         mptsas_smp_t *sp;
14305 
14306         ASSERT(MUTEX_HELD(&mpt->m_mutex));
14307 
14308         /*
14309          * TODO after hard reset, update the driver data structures
14310          * 1. update port/phymask mapping table mpt->m_phy_info
14311          * 2. invalid all the entries in hash table
14312          *    m_devhdl = 0xffff and m_deviceinfo = 0
14313          * 3. call sas_device_page/expander_page to update hash table
14314          */
14315         mptsas_update_phymask(mpt);
14316         /*
14317          * Invalid the existing entries
14318          *
14319          * XXX - It seems like we should just delete everything here.  We are
14320          * holding the lock and are about to refresh all the targets in both
14321          * hashes anyway.  Given the path we're in, what outstanding async
14322          * event could possibly be trying to reference one of these things
14323          * without taking the lock, and how would that be useful anyway?
14324          */
14325         for (tp = refhash_first(mpt->m_targets); tp != NULL;
14326             tp = refhash_next(mpt->m_targets, tp)) {
14327                 tp->m_devhdl = MPTSAS_INVALID_DEVHDL;
14328                 tp->m_deviceinfo = 0;
14329                 tp->m_dr_flag = MPTSAS_DR_INACTIVE;
14330         }
14331         for (sp = refhash_first(mpt->m_smp_targets); sp != NULL;
14332             sp = refhash_next(mpt->m_smp_targets, sp)) {
14333                 sp->m_devhdl = MPTSAS_INVALID_DEVHDL;
14334                 sp->m_deviceinfo = 0;
14335         }
14336         mpt->m_done_traverse_dev = 0;
14337         mpt->m_done_traverse_smp = 0;
14338         mpt->m_dev_handle = mpt->m_smp_devhdl = MPTSAS_INVALID_DEVHDL;
14339         mptsas_update_hashtab(mpt);
14340 }
14341 
14342 static void
14343 mptsas_config_all(dev_info_t *pdip)
14344 {
14345         dev_info_t      *smpdip = NULL;
14346         mptsas_t        *mpt = DIP2MPT(pdip);
14347         int             phymask = 0;
14348         mptsas_phymask_t phy_mask;
14349         mptsas_target_t *ptgt = NULL;
14350         mptsas_smp_t    *psmp;
14351 
14352         /*
14353          * Get the phymask associated to the iport
14354          */
14355         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
14356             "phymask", 0);
14357 
14358         /*
14359          * Enumerate RAID volumes here (phymask == 0).
14360          */
14361         if (phymask == 0) {
14362                 mptsas_config_all_viport(pdip);
14363                 return;
14364         }
14365 
14366         mutex_enter(&mpt->m_mutex);
14367 
14368         if (!mpt->m_done_traverse_dev || !mpt->m_done_traverse_smp) {
14369                 mptsas_update_hashtab(mpt);
14370         }
14371 
14372         for (psmp = refhash_first(mpt->m_smp_targets); psmp != NULL;
14373             psmp = refhash_next(mpt->m_smp_targets, psmp)) {
14374                 phy_mask = psmp->m_addr.mta_phymask;
14375                 if (phy_mask == phymask) {
14376                         smpdip = NULL;
14377                         mutex_exit(&mpt->m_mutex);
14378                         (void) mptsas_online_smp(pdip, psmp, &smpdip);
14379                         mutex_enter(&mpt->m_mutex);
14380                 }
14381         }
14382 
14383         for (ptgt = refhash_first(mpt->m_targets); ptgt != NULL;
14384             ptgt = refhash_next(mpt->m_targets, ptgt)) {
14385                 phy_mask = ptgt->m_addr.mta_phymask;
14386                 if (phy_mask == phymask) {
14387                         mutex_exit(&mpt->m_mutex);
14388                         (void) mptsas_config_target(pdip, ptgt);
14389                         mutex_enter(&mpt->m_mutex);
14390                 }
14391         }
14392         mutex_exit(&mpt->m_mutex);
14393 }
14394 
14395 static int
14396 mptsas_config_target(dev_info_t *pdip, mptsas_target_t *ptgt)
14397 {
14398         int             rval = DDI_FAILURE;
14399         dev_info_t      *tdip;
14400 
14401         rval = mptsas_config_luns(pdip, ptgt);
14402         if (rval != DDI_SUCCESS) {
14403                 /*
14404                  * The return value means the SCMD_REPORT_LUNS
14405                  * did not execute successfully. The target maybe
14406                  * doesn't support such command.
14407                  */
14408                 rval = mptsas_probe_lun(pdip, 0, &tdip, ptgt);
14409         }
14410         return (rval);
14411 }
14412 
14413 /*
14414  * Return fail if not all the childs/paths are freed.
14415  * if there is any path under the HBA, the return value will be always fail
14416  * because we didn't call mdi_pi_free for path
14417  */
14418 static int
14419 mptsas_offline_target(dev_info_t *pdip, char *name)
14420 {
14421         dev_info_t              *child = NULL, *prechild = NULL;
14422         mdi_pathinfo_t          *pip = NULL, *savepip = NULL;
14423         int                     tmp_rval, rval = DDI_SUCCESS;
14424         char                    *addr, *cp;
14425         size_t                  s;
14426         mptsas_t                *mpt = DIP2MPT(pdip);
14427 
14428         child = ddi_get_child(pdip);
14429         while (child) {
14430                 addr = ddi_get_name_addr(child);
14431                 prechild = child;
14432                 child = ddi_get_next_sibling(child);
14433 
14434                 if (addr == NULL) {
14435                         continue;
14436                 }
14437                 if ((cp = strchr(addr, ',')) == NULL) {
14438                         continue;
14439                 }
14440 
14441                 s = (uintptr_t)cp - (uintptr_t)addr;
14442 
14443                 if (strncmp(addr, name, s) != 0) {
14444                         continue;
14445                 }
14446 
14447                 tmp_rval = mptsas_offline_lun(pdip, prechild, NULL,
14448                     NDI_DEVI_REMOVE);
14449                 if (tmp_rval != DDI_SUCCESS) {
14450                         rval = DDI_FAILURE;
14451                         if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
14452                             prechild, MPTSAS_DEV_GONE) !=
14453                             DDI_PROP_SUCCESS) {
14454                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
14455                                     "unable to create property for "
14456                                     "SAS %s (MPTSAS_DEV_GONE)", addr);
14457                         }
14458                 }
14459         }
14460 
14461         pip = mdi_get_next_client_path(pdip, NULL);
14462         while (pip) {
14463                 addr = MDI_PI(pip)->pi_addr;
14464                 savepip = pip;
14465                 pip = mdi_get_next_client_path(pdip, pip);
14466                 if (addr == NULL) {
14467                         continue;
14468                 }
14469 
14470                 if ((cp = strchr(addr, ',')) == NULL) {
14471                         continue;
14472                 }
14473 
14474                 s = (uintptr_t)cp - (uintptr_t)addr;
14475 
14476                 if (strncmp(addr, name, s) != 0) {
14477                         continue;
14478                 }
14479 
14480                 (void) mptsas_offline_lun(pdip, NULL, savepip,
14481                     NDI_DEVI_REMOVE);
14482                 /*
14483                  * driver will not invoke mdi_pi_free, so path will not
14484                  * be freed forever, return DDI_FAILURE.
14485                  */
14486                 rval = DDI_FAILURE;
14487         }
14488         return (rval);
14489 }
14490 
14491 static int
14492 mptsas_offline_lun(dev_info_t *pdip, dev_info_t *rdip,
14493     mdi_pathinfo_t *rpip, uint_t flags)
14494 {
14495         int             rval = DDI_FAILURE;
14496         char            *devname;
14497         dev_info_t      *cdip, *parent;
14498 
14499         if (rpip != NULL) {
14500                 parent = scsi_vhci_dip;
14501                 cdip = mdi_pi_get_client(rpip);
14502         } else if (rdip != NULL) {
14503                 parent = pdip;
14504                 cdip = rdip;
14505         } else {
14506                 return (DDI_FAILURE);
14507         }
14508 
14509         /*
14510          * Make sure node is attached otherwise
14511          * it won't have related cache nodes to
14512          * clean up.  i_ddi_devi_attached is
14513          * similiar to i_ddi_node_state(cdip) >=
14514          * DS_ATTACHED.
14515          */
14516         if (i_ddi_devi_attached(cdip)) {
14517 
14518                 /* Get full devname */
14519                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14520                 (void) ddi_deviname(cdip, devname);
14521                 /* Clean cache */
14522                 (void) devfs_clean(parent, devname + 1,
14523                     DV_CLEAN_FORCE);
14524                 kmem_free(devname, MAXNAMELEN + 1);
14525         }
14526         if (rpip != NULL) {
14527                 if (MDI_PI_IS_OFFLINE(rpip)) {
14528                         rval = DDI_SUCCESS;
14529                 } else {
14530                         rval = mdi_pi_offline(rpip, 0);
14531                 }
14532         } else {
14533                 rval = ndi_devi_offline(cdip, flags);
14534         }
14535 
14536         return (rval);
14537 }
14538 
14539 static dev_info_t *
14540 mptsas_find_smp_child(dev_info_t *parent, char *str_wwn)
14541 {
14542         dev_info_t      *child = NULL;
14543         char            *smp_wwn = NULL;
14544 
14545         child = ddi_get_child(parent);
14546         while (child) {
14547                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
14548                     DDI_PROP_DONTPASS, SMP_WWN, &smp_wwn)
14549                     != DDI_SUCCESS) {
14550                         child = ddi_get_next_sibling(child);
14551                         continue;
14552                 }
14553 
14554                 if (strcmp(smp_wwn, str_wwn) == 0) {
14555                         ddi_prop_free(smp_wwn);
14556                         break;
14557                 }
14558                 child = ddi_get_next_sibling(child);
14559                 ddi_prop_free(smp_wwn);
14560         }
14561         return (child);
14562 }
14563 
14564 static int
14565 mptsas_offline_smp(dev_info_t *pdip, mptsas_smp_t *smp_node, uint_t flags)
14566 {
14567         int             rval = DDI_FAILURE;
14568         char            *devname;
14569         char            wwn_str[MPTSAS_WWN_STRLEN];
14570         dev_info_t      *cdip;
14571 
14572         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
14573 
14574         cdip = mptsas_find_smp_child(pdip, wwn_str);
14575 
14576         if (cdip == NULL)
14577                 return (DDI_SUCCESS);
14578 
14579         /*
14580          * Make sure node is attached otherwise
14581          * it won't have related cache nodes to
14582          * clean up.  i_ddi_devi_attached is
14583          * similiar to i_ddi_node_state(cdip) >=
14584          * DS_ATTACHED.
14585          */
14586         if (i_ddi_devi_attached(cdip)) {
14587 
14588                 /* Get full devname */
14589                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
14590                 (void) ddi_deviname(cdip, devname);
14591                 /* Clean cache */
14592                 (void) devfs_clean(pdip, devname + 1,
14593                     DV_CLEAN_FORCE);
14594                 kmem_free(devname, MAXNAMELEN + 1);
14595         }
14596 
14597         rval = ndi_devi_offline(cdip, flags);
14598 
14599         return (rval);
14600 }
14601 
14602 static dev_info_t *
14603 mptsas_find_child(dev_info_t *pdip, char *name)
14604 {
14605         dev_info_t      *child = NULL;
14606         char            *rname = NULL;
14607         int             rval = DDI_FAILURE;
14608 
14609         rname = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14610 
14611         child = ddi_get_child(pdip);
14612         while (child) {
14613                 rval = mptsas_name_child(child, rname, SCSI_MAXNAMELEN);
14614                 if (rval != DDI_SUCCESS) {
14615                         child = ddi_get_next_sibling(child);
14616                         bzero(rname, SCSI_MAXNAMELEN);
14617                         continue;
14618                 }
14619 
14620                 if (strcmp(rname, name) == 0) {
14621                         break;
14622                 }
14623                 child = ddi_get_next_sibling(child);
14624                 bzero(rname, SCSI_MAXNAMELEN);
14625         }
14626 
14627         kmem_free(rname, SCSI_MAXNAMELEN);
14628 
14629         return (child);
14630 }
14631 
14632 
14633 static dev_info_t *
14634 mptsas_find_child_addr(dev_info_t *pdip, uint64_t sasaddr, int lun)
14635 {
14636         dev_info_t      *child = NULL;
14637         char            *name = NULL;
14638         char            *addr = NULL;
14639 
14640         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14641         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14642         (void) sprintf(name, "%016"PRIx64, sasaddr);
14643         (void) sprintf(addr, "w%s,%x", name, lun);
14644         child = mptsas_find_child(pdip, addr);
14645         kmem_free(name, SCSI_MAXNAMELEN);
14646         kmem_free(addr, SCSI_MAXNAMELEN);
14647         return (child);
14648 }
14649 
14650 static dev_info_t *
14651 mptsas_find_child_phy(dev_info_t *pdip, uint8_t phy)
14652 {
14653         dev_info_t      *child;
14654         char            *addr;
14655 
14656         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14657         (void) sprintf(addr, "p%x,0", phy);
14658         child = mptsas_find_child(pdip, addr);
14659         kmem_free(addr, SCSI_MAXNAMELEN);
14660         return (child);
14661 }
14662 
14663 static mdi_pathinfo_t *
14664 mptsas_find_path_phy(dev_info_t *pdip, uint8_t phy)
14665 {
14666         mdi_pathinfo_t  *path;
14667         char            *addr = NULL;
14668 
14669         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14670         (void) sprintf(addr, "p%x,0", phy);
14671         path = mdi_pi_find(pdip, NULL, addr);
14672         kmem_free(addr, SCSI_MAXNAMELEN);
14673         return (path);
14674 }
14675 
14676 static mdi_pathinfo_t *
14677 mptsas_find_path_addr(dev_info_t *parent, uint64_t sasaddr, int lun)
14678 {
14679         mdi_pathinfo_t  *path;
14680         char            *name = NULL;
14681         char            *addr = NULL;
14682 
14683         name = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14684         addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14685         (void) sprintf(name, "%016"PRIx64, sasaddr);
14686         (void) sprintf(addr, "w%s,%x", name, lun);
14687         path = mdi_pi_find(parent, NULL, addr);
14688         kmem_free(name, SCSI_MAXNAMELEN);
14689         kmem_free(addr, SCSI_MAXNAMELEN);
14690 
14691         return (path);
14692 }
14693 
14694 static int
14695 mptsas_create_lun(dev_info_t *pdip, struct scsi_inquiry *sd_inq,
14696     dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
14697 {
14698         int                     i = 0;
14699         uchar_t                 *inq83 = NULL;
14700         int                     inq83_len1 = 0xFF;
14701         int                     inq83_len = 0;
14702         int                     rval = DDI_FAILURE;
14703         ddi_devid_t             devid;
14704         char                    *guid = NULL;
14705         int                     target = ptgt->m_devhdl;
14706         mdi_pathinfo_t          *pip = NULL;
14707         mptsas_t                *mpt = DIP2MPT(pdip);
14708 
14709         /*
14710          * For DVD/CD ROM and tape devices and optical
14711          * devices, we won't try to enumerate them under
14712          * scsi_vhci, so no need to try page83
14713          */
14714         if (sd_inq && (sd_inq->inq_dtype == DTYPE_RODIRECT ||
14715             sd_inq->inq_dtype == DTYPE_OPTICAL ||
14716             sd_inq->inq_dtype == DTYPE_ESI))
14717                 goto create_lun;
14718 
14719         /*
14720          * The LCA returns good SCSI status, but corrupt page 83 data the first
14721          * time it is queried. The solution is to keep trying to request page83
14722          * and verify the GUID is not (DDI_NOT_WELL_FORMED) in
14723          * mptsas_inq83_retry_timeout seconds. If the timeout expires, driver
14724          * give up to get VPD page at this stage and fail the enumeration.
14725          */
14726 
14727         inq83   = kmem_zalloc(inq83_len1, KM_SLEEP);
14728 
14729         for (i = 0; i < mptsas_inq83_retry_timeout; i++) {
14730                 rval = mptsas_inquiry(mpt, ptgt, lun, 0x83, inq83,
14731                     inq83_len1, &inq83_len, 1);
14732                 if (rval != 0) {
14733                         mptsas_log(mpt, CE_WARN, "!mptsas request inquiry page "
14734                             "0x83 for target:%x, lun:%x failed!", target, lun);
14735                         if (mptsas_physical_bind_failed_page_83 != B_FALSE)
14736                                 goto create_lun;
14737                         goto out;
14738                 }
14739                 /*
14740                  * create DEVID from inquiry data
14741                  */
14742                 if ((rval = ddi_devid_scsi_encode(
14743                     DEVID_SCSI_ENCODE_VERSION_LATEST, NULL, (uchar_t *)sd_inq,
14744                     sizeof (struct scsi_inquiry), NULL, 0, inq83,
14745                     (size_t)inq83_len, &devid)) == DDI_SUCCESS) {
14746                         /*
14747                          * extract GUID from DEVID
14748                          */
14749                         guid = ddi_devid_to_guid(devid);
14750 
14751                         /*
14752                          * Do not enable MPXIO if the strlen(guid) is greater
14753                          * than MPTSAS_MAX_GUID_LEN, this constrain would be
14754                          * handled by framework later.
14755                          */
14756                         if (guid && (strlen(guid) > MPTSAS_MAX_GUID_LEN)) {
14757                                 ddi_devid_free_guid(guid);
14758                                 guid = NULL;
14759                                 if (mpt->m_mpxio_enable == TRUE) {
14760                                         mptsas_log(mpt, CE_NOTE, "!Target:%x, "
14761                                             "lun:%x doesn't have a valid GUID, "
14762                                             "multipathing for this drive is "
14763                                             "not enabled", target, lun);
14764                                 }
14765                         }
14766 
14767                         /*
14768                          * devid no longer needed
14769                          */
14770                         ddi_devid_free(devid);
14771                         break;
14772                 } else if (rval == DDI_NOT_WELL_FORMED) {
14773                         /*
14774                          * return value of ddi_devid_scsi_encode equal to
14775                          * DDI_NOT_WELL_FORMED means DEVID_RETRY, it worth
14776                          * to retry inquiry page 0x83 and get GUID.
14777                          */
14778                         NDBG20(("Not well formed devid, retry..."));
14779                         delay(1 * drv_usectohz(1000000));
14780                         continue;
14781                 } else {
14782                         mptsas_log(mpt, CE_WARN, "!Encode devid failed for "
14783                             "path target:%x, lun:%x", target, lun);
14784                         rval = DDI_FAILURE;
14785                         goto create_lun;
14786                 }
14787         }
14788 
14789         if (i == mptsas_inq83_retry_timeout) {
14790                 mptsas_log(mpt, CE_WARN, "!Repeated page83 requests timeout "
14791                     "for path target:%x, lun:%x", target, lun);
14792         }
14793 
14794         rval = DDI_FAILURE;
14795 
14796 create_lun:
14797         if ((guid != NULL) && (mpt->m_mpxio_enable == TRUE)) {
14798                 rval = mptsas_create_virt_lun(pdip, sd_inq, guid, lun_dip, &pip,
14799                     ptgt, lun);
14800         }
14801         if (rval != DDI_SUCCESS) {
14802                 rval = mptsas_create_phys_lun(pdip, sd_inq, guid, lun_dip,
14803                     ptgt, lun);
14804 
14805         }
14806 out:
14807         if (guid != NULL) {
14808                 /*
14809                  * guid no longer needed
14810                  */
14811                 ddi_devid_free_guid(guid);
14812         }
14813         if (inq83 != NULL)
14814                 kmem_free(inq83, inq83_len1);
14815         return (rval);
14816 }
14817 
14818 static int
14819 mptsas_create_virt_lun(dev_info_t *pdip, struct scsi_inquiry *inq, char *guid,
14820     dev_info_t **lun_dip, mdi_pathinfo_t **pip, mptsas_target_t *ptgt, int lun)
14821 {
14822         int                     target;
14823         char                    *nodename = NULL;
14824         char                    **compatible = NULL;
14825         int                     ncompatible     = 0;
14826         int                     mdi_rtn = MDI_FAILURE;
14827         int                     rval = DDI_FAILURE;
14828         char                    *old_guid = NULL;
14829         mptsas_t                *mpt = DIP2MPT(pdip);
14830         char                    *lun_addr = NULL;
14831         char                    *wwn_str = NULL;
14832         char                    *attached_wwn_str = NULL;
14833         char                    *component = NULL;
14834         uint8_t                 phy = 0xFF;
14835         uint64_t                sas_wwn;
14836         int64_t                 lun64 = 0;
14837         uint32_t                devinfo;
14838         uint16_t                dev_hdl;
14839         uint16_t                pdev_hdl;
14840         uint64_t                dev_sas_wwn;
14841         uint64_t                pdev_sas_wwn;
14842         uint32_t                pdev_info;
14843         uint8_t                 physport;
14844         uint8_t                 phy_id;
14845         uint32_t                page_address;
14846         uint16_t                bay_num, enclosure, io_flags;
14847         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
14848         uint32_t                dev_info;
14849 
14850         mutex_enter(&mpt->m_mutex);
14851         target = ptgt->m_devhdl;
14852         sas_wwn = ptgt->m_addr.mta_wwn;
14853         devinfo = ptgt->m_deviceinfo;
14854         phy = ptgt->m_phynum;
14855         mutex_exit(&mpt->m_mutex);
14856 
14857         if (sas_wwn) {
14858                 *pip = mptsas_find_path_addr(pdip, sas_wwn, lun);
14859         } else {
14860                 *pip = mptsas_find_path_phy(pdip, phy);
14861         }
14862 
14863         if (*pip != NULL) {
14864                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
14865                 ASSERT(*lun_dip != NULL);
14866                 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, *lun_dip,
14867                     (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
14868                     MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) {
14869                         if (strncmp(guid, old_guid, strlen(guid)) == 0) {
14870                                 /*
14871                                  * Same path back online again.
14872                                  */
14873                                 (void) ddi_prop_free(old_guid);
14874                                 if ((!MDI_PI_IS_ONLINE(*pip)) &&
14875                                     (!MDI_PI_IS_STANDBY(*pip)) &&
14876                                     (ptgt->m_tgt_unconfigured == 0)) {
14877                                         rval = mdi_pi_online(*pip, 0);
14878                                         mutex_enter(&mpt->m_mutex);
14879                                         ptgt->m_led_status = 0;
14880                                         (void) mptsas_flush_led_status(mpt,
14881                                             ptgt);
14882                                         mutex_exit(&mpt->m_mutex);
14883                                 } else {
14884                                         rval = DDI_SUCCESS;
14885                                 }
14886                                 if (rval != DDI_SUCCESS) {
14887                                         mptsas_log(mpt, CE_WARN, "path:target: "
14888                                             "%x, lun:%x online failed!", target,
14889                                             lun);
14890                                         *pip = NULL;
14891                                         *lun_dip = NULL;
14892                                 }
14893                                 return (rval);
14894                         } else {
14895                                 /*
14896                                  * The GUID of the LUN has changed which maybe
14897                                  * because customer mapped another volume to the
14898                                  * same LUN.
14899                                  */
14900                                 mptsas_log(mpt, CE_WARN, "The GUID of the "
14901                                     "target:%x, lun:%x was changed, maybe "
14902                                     "because someone mapped another volume "
14903                                     "to the same LUN", target, lun);
14904                                 (void) ddi_prop_free(old_guid);
14905                                 if (!MDI_PI_IS_OFFLINE(*pip)) {
14906                                         rval = mdi_pi_offline(*pip, 0);
14907                                         if (rval != MDI_SUCCESS) {
14908                                                 mptsas_log(mpt, CE_WARN, "path:"
14909                                                     "target:%x, lun:%x offline "
14910                                                     "failed!", target, lun);
14911                                                 *pip = NULL;
14912                                                 *lun_dip = NULL;
14913                                                 return (DDI_FAILURE);
14914                                         }
14915                                 }
14916                                 if (mdi_pi_free(*pip, 0) != MDI_SUCCESS) {
14917                                         mptsas_log(mpt, CE_WARN, "path:target:"
14918                                             "%x, lun:%x free failed!", target,
14919                                             lun);
14920                                         *pip = NULL;
14921                                         *lun_dip = NULL;
14922                                         return (DDI_FAILURE);
14923                                 }
14924                         }
14925                 } else {
14926                         mptsas_log(mpt, CE_WARN, "Can't get client-guid "
14927                             "property for path:target:%x, lun:%x", target, lun);
14928                         *pip = NULL;
14929                         *lun_dip = NULL;
14930                         return (DDI_FAILURE);
14931                 }
14932         }
14933         scsi_hba_nodename_compatible_get(inq, NULL,
14934             inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
14935 
14936         /*
14937          * if nodename can't be determined then print a message and skip it
14938          */
14939         if (nodename == NULL) {
14940                 mptsas_log(mpt, CE_WARN, "mptsas driver found no compatible "
14941                     "driver for target%d lun %d dtype:0x%02x", target, lun,
14942                     inq->inq_dtype);
14943                 return (DDI_FAILURE);
14944         }
14945 
14946         wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
14947         /* The property is needed by MPAPI */
14948         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
14949 
14950         lun_addr = kmem_zalloc(SCSI_MAXNAMELEN, KM_SLEEP);
14951         if (guid) {
14952                 (void) sprintf(lun_addr, "w%s,%x", wwn_str, lun);
14953                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
14954         } else {
14955                 (void) sprintf(lun_addr, "p%x,%x", phy, lun);
14956                 (void) sprintf(wwn_str, "p%x", phy);
14957         }
14958 
14959         mdi_rtn = mdi_pi_alloc_compatible(pdip, nodename,
14960             guid, lun_addr, compatible, ncompatible,
14961             0, pip);
14962         if (mdi_rtn == MDI_SUCCESS) {
14963 
14964                 if (mdi_prop_update_string(*pip, MDI_GUID,
14965                     guid) != DDI_SUCCESS) {
14966                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14967                             "create prop for target %d lun %d (MDI_GUID)",
14968                             target, lun);
14969                         mdi_rtn = MDI_FAILURE;
14970                         goto virt_create_done;
14971                 }
14972 
14973                 if (mdi_prop_update_int(*pip, LUN_PROP,
14974                     lun) != DDI_SUCCESS) {
14975                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14976                             "create prop for target %d lun %d (LUN_PROP)",
14977                             target, lun);
14978                         mdi_rtn = MDI_FAILURE;
14979                         goto virt_create_done;
14980                 }
14981                 lun64 = (int64_t)lun;
14982                 if (mdi_prop_update_int64(*pip, LUN64_PROP,
14983                     lun64) != DDI_SUCCESS) {
14984                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14985                             "create prop for target %d (LUN64_PROP)",
14986                             target);
14987                         mdi_rtn = MDI_FAILURE;
14988                         goto virt_create_done;
14989                 }
14990                 if (mdi_prop_update_string_array(*pip, "compatible",
14991                     compatible, ncompatible) !=
14992                     DDI_PROP_SUCCESS) {
14993                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
14994                             "create prop for target %d lun %d (COMPATIBLE)",
14995                             target, lun);
14996                         mdi_rtn = MDI_FAILURE;
14997                         goto virt_create_done;
14998                 }
14999                 if (sas_wwn && (mdi_prop_update_string(*pip,
15000                     SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS)) {
15001                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15002                             "create prop for target %d lun %d "
15003                             "(target-port)", target, lun);
15004                         mdi_rtn = MDI_FAILURE;
15005                         goto virt_create_done;
15006                 } else if ((sas_wwn == 0) && (mdi_prop_update_int(*pip,
15007                     "sata-phy", phy) != DDI_PROP_SUCCESS)) {
15008                         /*
15009                          * Direct attached SATA device without DeviceName
15010                          */
15011                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15012                             "create prop for SAS target %d lun %d "
15013                             "(sata-phy)", target, lun);
15014                         mdi_rtn = MDI_FAILURE;
15015                         goto virt_create_done;
15016                 }
15017                 mutex_enter(&mpt->m_mutex);
15018 
15019                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15020                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15021                     (uint32_t)ptgt->m_devhdl;
15022                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15023                     &dev_hdl, &dev_sas_wwn, &dev_info, &physport,
15024                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15025                 if (rval != DDI_SUCCESS) {
15026                         mutex_exit(&mpt->m_mutex);
15027                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15028                             "parent device for handle %d", page_address);
15029                         mdi_rtn = MDI_FAILURE;
15030                         goto virt_create_done;
15031                 }
15032 
15033                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15034                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
15035                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15036                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
15037                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15038                 if (rval != DDI_SUCCESS) {
15039                         mutex_exit(&mpt->m_mutex);
15040                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
15041                             "device info for handle %d", page_address);
15042                         mdi_rtn = MDI_FAILURE;
15043                         goto virt_create_done;
15044                 }
15045 
15046                 mutex_exit(&mpt->m_mutex);
15047 
15048                 /*
15049                  * If this device direct attached to the controller
15050                  * set the attached-port to the base wwid
15051                  */
15052                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15053                     != DEVINFO_DIRECT_ATTACHED) {
15054                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15055                             pdev_sas_wwn);
15056                 } else {
15057                         /*
15058                          * Update the iport's attached-port to guid
15059                          */
15060                         if (sas_wwn == 0) {
15061                                 (void) sprintf(wwn_str, "p%x", phy);
15062                         } else {
15063                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15064                         }
15065                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
15066                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15067                             DDI_PROP_SUCCESS) {
15068                                 mptsas_log(mpt, CE_WARN,
15069                                     "mptsas unable to create "
15070                                     "property for iport target-port"
15071                                     " %s (sas_wwn)",
15072                                     wwn_str);
15073                                 mdi_rtn = MDI_FAILURE;
15074                                 goto virt_create_done;
15075                         }
15076 
15077                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15078                             mpt->un.m_base_wwid);
15079                 }
15080 
15081                 if (mdi_prop_update_string(*pip,
15082                     SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
15083                     DDI_PROP_SUCCESS) {
15084                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15085                             "property for iport attached-port %s (sas_wwn)",
15086                             attached_wwn_str);
15087                         mdi_rtn = MDI_FAILURE;
15088                         goto virt_create_done;
15089                 }
15090 
15091 
15092                 if (inq->inq_dtype == 0) {
15093                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
15094                         /*
15095                          * set obp path for pathinfo
15096                          */
15097                         (void) snprintf(component, MAXPATHLEN,
15098                             "disk@%s", lun_addr);
15099 
15100                         if (mdi_pi_pathname_obp_set(*pip, component) !=
15101                             DDI_SUCCESS) {
15102                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
15103                                     "unable to set obp-path for object %s",
15104                                     component);
15105                                 mdi_rtn = MDI_FAILURE;
15106                                 goto virt_create_done;
15107                         }
15108                 }
15109 
15110                 *lun_dip = MDI_PI(*pip)->pi_client->ct_dip;
15111                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
15112                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
15113                         if ((ndi_prop_update_int(DDI_DEV_T_NONE, *lun_dip,
15114                             "pm-capable", 1)) !=
15115                             DDI_PROP_SUCCESS) {
15116                                 mptsas_log(mpt, CE_WARN, "mptsas driver"
15117                                     "failed to create pm-capable "
15118                                     "property, target %d", target);
15119                                 mdi_rtn = MDI_FAILURE;
15120                                 goto virt_create_done;
15121                         }
15122                 }
15123                 /*
15124                  * Create the phy-num property
15125                  */
15126                 if (mdi_prop_update_int(*pip, "phy-num",
15127                     ptgt->m_phynum) != DDI_SUCCESS) {
15128                         mptsas_log(mpt, CE_WARN, "mptsas driver unable to "
15129                             "create phy-num property for target %d lun %d",
15130                             target, lun);
15131                         mdi_rtn = MDI_FAILURE;
15132                         goto virt_create_done;
15133                 }
15134                 NDBG20(("new path:%s onlining,", MDI_PI(*pip)->pi_addr));
15135                 mdi_rtn = mdi_pi_online(*pip, 0);
15136                 if (mdi_rtn == MDI_SUCCESS) {
15137                         mutex_enter(&mpt->m_mutex);
15138                         ptgt->m_led_status = 0;
15139                         (void) mptsas_flush_led_status(mpt, ptgt);
15140                         mutex_exit(&mpt->m_mutex);
15141                 }
15142                 if (mdi_rtn == MDI_NOT_SUPPORTED) {
15143                         mdi_rtn = MDI_FAILURE;
15144                 }
15145 virt_create_done:
15146                 if (*pip && mdi_rtn != MDI_SUCCESS) {
15147                         (void) mdi_pi_free(*pip, 0);
15148                         *pip = NULL;
15149                         *lun_dip = NULL;
15150                 }
15151         }
15152 
15153         scsi_hba_nodename_compatible_free(nodename, compatible);
15154         if (lun_addr != NULL) {
15155                 kmem_free(lun_addr, SCSI_MAXNAMELEN);
15156         }
15157         if (wwn_str != NULL) {
15158                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
15159         }
15160         if (component != NULL) {
15161                 kmem_free(component, MAXPATHLEN);
15162         }
15163 
15164         return ((mdi_rtn == MDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15165 }
15166 
15167 static int
15168 mptsas_create_phys_lun(dev_info_t *pdip, struct scsi_inquiry *inq,
15169     char *guid, dev_info_t **lun_dip, mptsas_target_t *ptgt, int lun)
15170 {
15171         int                     target;
15172         int                     rval;
15173         int                     ndi_rtn = NDI_FAILURE;
15174         uint64_t                be_sas_wwn;
15175         char                    *nodename = NULL;
15176         char                    **compatible = NULL;
15177         int                     ncompatible = 0;
15178         int                     instance = 0;
15179         mptsas_t                *mpt = DIP2MPT(pdip);
15180         char                    *wwn_str = NULL;
15181         char                    *component = NULL;
15182         char                    *attached_wwn_str = NULL;
15183         uint8_t                 phy = 0xFF;
15184         uint64_t                sas_wwn;
15185         uint32_t                devinfo;
15186         uint16_t                dev_hdl;
15187         uint16_t                pdev_hdl;
15188         uint64_t                pdev_sas_wwn;
15189         uint64_t                dev_sas_wwn;
15190         uint32_t                pdev_info;
15191         uint8_t                 physport;
15192         uint8_t                 phy_id;
15193         uint32_t                page_address;
15194         uint16_t                bay_num, enclosure, io_flags;
15195         char                    pdev_wwn_str[MPTSAS_WWN_STRLEN];
15196         uint32_t                dev_info;
15197         int64_t                 lun64 = 0;
15198 
15199         mutex_enter(&mpt->m_mutex);
15200         target = ptgt->m_devhdl;
15201         sas_wwn = ptgt->m_addr.mta_wwn;
15202         devinfo = ptgt->m_deviceinfo;
15203         phy = ptgt->m_phynum;
15204         mutex_exit(&mpt->m_mutex);
15205 
15206         /*
15207          * generate compatible property with binding-set "mpt"
15208          */
15209         scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL,
15210             &nodename, &compatible, &ncompatible);
15211 
15212         /*
15213          * if nodename can't be determined then print a message and skip it
15214          */
15215         if (nodename == NULL) {
15216                 mptsas_log(mpt, CE_WARN, "mptsas found no compatible driver "
15217                     "for target %d lun %d", target, lun);
15218                 return (DDI_FAILURE);
15219         }
15220 
15221         ndi_rtn = ndi_devi_alloc(pdip, nodename,
15222             DEVI_SID_NODEID, lun_dip);
15223 
15224         /*
15225          * if lun alloc success, set props
15226          */
15227         if (ndi_rtn == NDI_SUCCESS) {
15228 
15229                 if (ndi_prop_update_int(DDI_DEV_T_NONE,
15230                     *lun_dip, LUN_PROP, lun) !=
15231                     DDI_PROP_SUCCESS) {
15232                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15233                             "property for target %d lun %d (LUN_PROP)",
15234                             target, lun);
15235                         ndi_rtn = NDI_FAILURE;
15236                         goto phys_create_done;
15237                 }
15238 
15239                 lun64 = (int64_t)lun;
15240                 if (ndi_prop_update_int64(DDI_DEV_T_NONE,
15241                     *lun_dip, LUN64_PROP, lun64) !=
15242                     DDI_PROP_SUCCESS) {
15243                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15244                             "property for target %d lun64 %d (LUN64_PROP)",
15245                             target, lun);
15246                         ndi_rtn = NDI_FAILURE;
15247                         goto phys_create_done;
15248                 }
15249                 if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
15250                     *lun_dip, "compatible", compatible, ncompatible)
15251                     != DDI_PROP_SUCCESS) {
15252                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15253                             "property for target %d lun %d (COMPATIBLE)",
15254                             target, lun);
15255                         ndi_rtn = NDI_FAILURE;
15256                         goto phys_create_done;
15257                 }
15258 
15259                 /*
15260                  * We need the SAS WWN for non-multipath devices, so
15261                  * we'll use the same property as that multipathing
15262                  * devices need to present for MPAPI. If we don't have
15263                  * a WWN (e.g. parallel SCSI), don't create the prop.
15264                  */
15265                 wwn_str = kmem_zalloc(MPTSAS_WWN_STRLEN, KM_SLEEP);
15266                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15267                 if (sas_wwn && ndi_prop_update_string(DDI_DEV_T_NONE,
15268                     *lun_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str)
15269                     != DDI_PROP_SUCCESS) {
15270                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15271                             "create property for SAS target %d lun %d "
15272                             "(target-port)", target, lun);
15273                         ndi_rtn = NDI_FAILURE;
15274                         goto phys_create_done;
15275                 }
15276 
15277                 be_sas_wwn = BE_64(sas_wwn);
15278                 if (sas_wwn && ndi_prop_update_byte_array(
15279                     DDI_DEV_T_NONE, *lun_dip, "port-wwn",
15280                     (uchar_t *)&be_sas_wwn, 8) != DDI_PROP_SUCCESS) {
15281                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15282                             "create property for SAS target %d lun %d "
15283                             "(port-wwn)", target, lun);
15284                         ndi_rtn = NDI_FAILURE;
15285                         goto phys_create_done;
15286                 } else if ((sas_wwn == 0) && (ndi_prop_update_int(
15287                     DDI_DEV_T_NONE, *lun_dip, "sata-phy", phy) !=
15288                     DDI_PROP_SUCCESS)) {
15289                         /*
15290                          * Direct attached SATA device without DeviceName
15291                          */
15292                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15293                             "create property for SAS target %d lun %d "
15294                             "(sata-phy)", target, lun);
15295                         ndi_rtn = NDI_FAILURE;
15296                         goto phys_create_done;
15297                 }
15298 
15299                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15300                     *lun_dip, SAS_PROP) != DDI_PROP_SUCCESS) {
15301                         mptsas_log(mpt, CE_WARN, "mptsas unable to"
15302                             "create property for SAS target %d lun %d"
15303                             " (SAS_PROP)", target, lun);
15304                         ndi_rtn = NDI_FAILURE;
15305                         goto phys_create_done;
15306                 }
15307                 if (guid && (ndi_prop_update_string(DDI_DEV_T_NONE,
15308                     *lun_dip, NDI_GUID, guid) != DDI_SUCCESS)) {
15309                         mptsas_log(mpt, CE_WARN, "mptsas unable "
15310                             "to create guid property for target %d "
15311                             "lun %d", target, lun);
15312                         ndi_rtn = NDI_FAILURE;
15313                         goto phys_create_done;
15314                 }
15315 
15316                 /*
15317                  * The following code is to set properties for SM-HBA support,
15318                  * it doesn't apply to RAID volumes
15319                  */
15320                 if (ptgt->m_addr.mta_phymask == 0)
15321                         goto phys_raid_lun;
15322 
15323                 mutex_enter(&mpt->m_mutex);
15324 
15325                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15326                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15327                     (uint32_t)ptgt->m_devhdl;
15328                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15329                     &dev_hdl, &dev_sas_wwn, &dev_info,
15330                     &physport, &phy_id, &pdev_hdl,
15331                     &bay_num, &enclosure, &io_flags);
15332                 if (rval != DDI_SUCCESS) {
15333                         mutex_exit(&mpt->m_mutex);
15334                         mptsas_log(mpt, CE_WARN, "mptsas unable to get"
15335                             "parent device for handle %d.", page_address);
15336                         ndi_rtn = NDI_FAILURE;
15337                         goto phys_create_done;
15338                 }
15339 
15340                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15341                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)pdev_hdl;
15342                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15343                     &dev_hdl, &pdev_sas_wwn, &pdev_info, &physport,
15344                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15345                 if (rval != DDI_SUCCESS) {
15346                         mutex_exit(&mpt->m_mutex);
15347                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15348                             "device for handle %d.", page_address);
15349                         ndi_rtn = NDI_FAILURE;
15350                         goto phys_create_done;
15351                 }
15352 
15353                 mutex_exit(&mpt->m_mutex);
15354 
15355                 /*
15356                  * If this device direct attached to the controller
15357                  * set the attached-port to the base wwid
15358                  */
15359                 if ((ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15360                     != DEVINFO_DIRECT_ATTACHED) {
15361                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15362                             pdev_sas_wwn);
15363                 } else {
15364                         /*
15365                          * Update the iport's attached-port to guid
15366                          */
15367                         if (sas_wwn == 0) {
15368                                 (void) sprintf(wwn_str, "p%x", phy);
15369                         } else {
15370                                 (void) sprintf(wwn_str, "w%016"PRIx64, sas_wwn);
15371                         }
15372                         if (ddi_prop_update_string(DDI_DEV_T_NONE,
15373                             pdip, SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15374                             DDI_PROP_SUCCESS) {
15375                                 mptsas_log(mpt, CE_WARN,
15376                                     "mptsas unable to create "
15377                                     "property for iport target-port"
15378                                     " %s (sas_wwn)",
15379                                     wwn_str);
15380                                 ndi_rtn = NDI_FAILURE;
15381                                 goto phys_create_done;
15382                         }
15383 
15384                         (void) sprintf(pdev_wwn_str, "w%016"PRIx64,
15385                             mpt->un.m_base_wwid);
15386                 }
15387 
15388                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15389                     *lun_dip, SCSI_ADDR_PROP_ATTACHED_PORT, pdev_wwn_str) !=
15390                     DDI_PROP_SUCCESS) {
15391                         mptsas_log(mpt, CE_WARN,
15392                             "mptsas unable to create "
15393                             "property for iport attached-port %s (sas_wwn)",
15394                             attached_wwn_str);
15395                         ndi_rtn = NDI_FAILURE;
15396                         goto phys_create_done;
15397                 }
15398 
15399                 if (IS_SATA_DEVICE(dev_info)) {
15400                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15401                             *lun_dip, MPTSAS_VARIANT, "sata") !=
15402                             DDI_PROP_SUCCESS) {
15403                                 mptsas_log(mpt, CE_WARN,
15404                                     "mptsas unable to create "
15405                                     "property for device variant ");
15406                                 ndi_rtn = NDI_FAILURE;
15407                                 goto phys_create_done;
15408                         }
15409                 }
15410 
15411                 if (IS_ATAPI_DEVICE(dev_info)) {
15412                         if (ndi_prop_update_string(DDI_DEV_T_NONE,
15413                             *lun_dip, MPTSAS_VARIANT, "atapi") !=
15414                             DDI_PROP_SUCCESS) {
15415                                 mptsas_log(mpt, CE_WARN,
15416                                     "mptsas unable to create "
15417                                     "property for device variant ");
15418                                 ndi_rtn = NDI_FAILURE;
15419                                 goto phys_create_done;
15420                         }
15421                 }
15422 
15423 phys_raid_lun:
15424                 /*
15425                  * if this is a SAS controller, and the target is a SATA
15426                  * drive, set the 'pm-capable' property for sd and if on
15427                  * an OPL platform, also check if this is an ATAPI
15428                  * device.
15429                  */
15430                 instance = ddi_get_instance(mpt->m_dip);
15431                 if (devinfo & (MPI2_SAS_DEVICE_INFO_SATA_DEVICE |
15432                     MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE)) {
15433                         NDBG2(("mptsas%d: creating pm-capable property, "
15434                             "target %d", instance, target));
15435 
15436                         if ((ndi_prop_update_int(DDI_DEV_T_NONE,
15437                             *lun_dip, "pm-capable", 1)) !=
15438                             DDI_PROP_SUCCESS) {
15439                                 mptsas_log(mpt, CE_WARN, "mptsas "
15440                                     "failed to create pm-capable "
15441                                     "property, target %d", target);
15442                                 ndi_rtn = NDI_FAILURE;
15443                                 goto phys_create_done;
15444                         }
15445 
15446                 }
15447 
15448                 if ((inq->inq_dtype == 0) || (inq->inq_dtype == 5)) {
15449                         /*
15450                          * add 'obp-path' properties for devinfo
15451                          */
15452                         bzero(wwn_str, sizeof (wwn_str));
15453                         (void) sprintf(wwn_str, "%016"PRIx64, sas_wwn);
15454                         component = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
15455                         if (guid) {
15456                                 (void) snprintf(component, MAXPATHLEN,
15457                                     "disk@w%s,%x", wwn_str, lun);
15458                         } else {
15459                                 (void) snprintf(component, MAXPATHLEN,
15460                                     "disk@p%x,%x", phy, lun);
15461                         }
15462                         if (ddi_pathname_obp_set(*lun_dip, component)
15463                             != DDI_SUCCESS) {
15464                                 mptsas_log(mpt, CE_WARN, "mpt_sas driver "
15465                                     "unable to set obp-path for SAS "
15466                                     "object %s", component);
15467                                 ndi_rtn = NDI_FAILURE;
15468                                 goto phys_create_done;
15469                         }
15470                 }
15471                 /*
15472                  * Create the phy-num property for non-raid disk
15473                  */
15474                 if (ptgt->m_addr.mta_phymask != 0) {
15475                         if (ndi_prop_update_int(DDI_DEV_T_NONE,
15476                             *lun_dip, "phy-num", ptgt->m_phynum) !=
15477                             DDI_PROP_SUCCESS) {
15478                                 mptsas_log(mpt, CE_WARN, "mptsas driver "
15479                                     "failed to create phy-num property for "
15480                                     "target %d", target);
15481                                 ndi_rtn = NDI_FAILURE;
15482                                 goto phys_create_done;
15483                         }
15484                 }
15485 phys_create_done:
15486                 /*
15487                  * If props were setup ok, online the lun
15488                  */
15489                 if (ndi_rtn == NDI_SUCCESS) {
15490                         /*
15491                          * Try to online the new node
15492                          */
15493                         ndi_rtn = ndi_devi_online(*lun_dip, NDI_ONLINE_ATTACH);
15494                 }
15495                 if (ndi_rtn == NDI_SUCCESS) {
15496                         mutex_enter(&mpt->m_mutex);
15497                         ptgt->m_led_status = 0;
15498                         (void) mptsas_flush_led_status(mpt, ptgt);
15499                         mutex_exit(&mpt->m_mutex);
15500                 }
15501 
15502                 /*
15503                  * If success set rtn flag, else unwire alloc'd lun
15504                  */
15505                 if (ndi_rtn != NDI_SUCCESS) {
15506                         NDBG12(("mptsas driver unable to online "
15507                             "target %d lun %d", target, lun));
15508                         ndi_prop_remove_all(*lun_dip);
15509                         (void) ndi_devi_free(*lun_dip);
15510                         *lun_dip = NULL;
15511                 }
15512         }
15513 
15514         scsi_hba_nodename_compatible_free(nodename, compatible);
15515 
15516         if (wwn_str != NULL) {
15517                 kmem_free(wwn_str, MPTSAS_WWN_STRLEN);
15518         }
15519         if (component != NULL) {
15520                 kmem_free(component, MAXPATHLEN);
15521         }
15522 
15523 
15524         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15525 }
15526 
15527 static int
15528 mptsas_probe_smp(dev_info_t *pdip, uint64_t wwn)
15529 {
15530         mptsas_t        *mpt = DIP2MPT(pdip);
15531         struct smp_device smp_sd;
15532 
15533         /* XXX An HBA driver should not be allocating an smp_device. */
15534         bzero(&smp_sd, sizeof (struct smp_device));
15535         smp_sd.smp_sd_address.smp_a_hba_tran = mpt->m_smptran;
15536         bcopy(&wwn, smp_sd.smp_sd_address.smp_a_wwn, SAS_WWN_BYTE_SIZE);
15537 
15538         if (smp_probe(&smp_sd) != DDI_PROBE_SUCCESS)
15539                 return (NDI_FAILURE);
15540         return (NDI_SUCCESS);
15541 }
15542 
15543 static int
15544 mptsas_config_smp(dev_info_t *pdip, uint64_t sas_wwn, dev_info_t **smp_dip)
15545 {
15546         mptsas_t        *mpt = DIP2MPT(pdip);
15547         mptsas_smp_t    *psmp = NULL;
15548         int             rval;
15549         int             phymask;
15550 
15551         /*
15552          * Get the physical port associated to the iport
15553          * PHYMASK TODO
15554          */
15555         phymask = ddi_prop_get_int(DDI_DEV_T_ANY, pdip, 0,
15556             "phymask", 0);
15557         /*
15558          * Find the smp node in hash table with specified sas address and
15559          * physical port
15560          */
15561         psmp = mptsas_wwid_to_psmp(mpt, phymask, sas_wwn);
15562         if (psmp == NULL) {
15563                 return (DDI_FAILURE);
15564         }
15565 
15566         rval = mptsas_online_smp(pdip, psmp, smp_dip);
15567 
15568         return (rval);
15569 }
15570 
15571 static int
15572 mptsas_online_smp(dev_info_t *pdip, mptsas_smp_t *smp_node,
15573     dev_info_t **smp_dip)
15574 {
15575         char            wwn_str[MPTSAS_WWN_STRLEN];
15576         char            attached_wwn_str[MPTSAS_WWN_STRLEN];
15577         int             ndi_rtn = NDI_FAILURE;
15578         int             rval = 0;
15579         mptsas_smp_t    dev_info;
15580         uint32_t        page_address;
15581         mptsas_t        *mpt = DIP2MPT(pdip);
15582         uint16_t        dev_hdl;
15583         uint64_t        sas_wwn;
15584         uint64_t        smp_sas_wwn;
15585         uint8_t         physport;
15586         uint8_t         phy_id;
15587         uint16_t        pdev_hdl;
15588         uint8_t         numphys = 0;
15589         uint16_t        i = 0;
15590         char            phymask[MPTSAS_MAX_PHYS];
15591         char            *iport = NULL;
15592         mptsas_phymask_t        phy_mask = 0;
15593         uint16_t        attached_devhdl;
15594         uint16_t        bay_num, enclosure, io_flags;
15595 
15596         (void) sprintf(wwn_str, "%"PRIx64, smp_node->m_addr.mta_wwn);
15597 
15598         /*
15599          * Probe smp device, prevent the node of removed device from being
15600          * configured succesfully
15601          */
15602         if (mptsas_probe_smp(pdip, smp_node->m_addr.mta_wwn) != NDI_SUCCESS) {
15603                 return (DDI_FAILURE);
15604         }
15605 
15606         if ((*smp_dip = mptsas_find_smp_child(pdip, wwn_str)) != NULL) {
15607                 return (DDI_SUCCESS);
15608         }
15609 
15610         ndi_rtn = ndi_devi_alloc(pdip, "smp", DEVI_SID_NODEID, smp_dip);
15611 
15612         /*
15613          * if lun alloc success, set props
15614          */
15615         if (ndi_rtn == NDI_SUCCESS) {
15616                 /*
15617                  * Set the flavor of the child to be SMP flavored
15618                  */
15619                 ndi_flavor_set(*smp_dip, SCSA_FLAVOR_SMP);
15620 
15621                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15622                     *smp_dip, SMP_WWN, wwn_str) !=
15623                     DDI_PROP_SUCCESS) {
15624                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15625                             "property for smp device %s (sas_wwn)",
15626                             wwn_str);
15627                         ndi_rtn = NDI_FAILURE;
15628                         goto smp_create_done;
15629                 }
15630                 (void) sprintf(wwn_str, "w%"PRIx64, smp_node->m_addr.mta_wwn);
15631                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15632                     *smp_dip, SCSI_ADDR_PROP_TARGET_PORT, wwn_str) !=
15633                     DDI_PROP_SUCCESS) {
15634                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15635                             "property for iport target-port %s (sas_wwn)",
15636                             wwn_str);
15637                         ndi_rtn = NDI_FAILURE;
15638                         goto smp_create_done;
15639                 }
15640 
15641                 mutex_enter(&mpt->m_mutex);
15642 
15643                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_HNDL &
15644                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | smp_node->m_devhdl;
15645                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
15646                     &dev_info);
15647                 if (rval != DDI_SUCCESS) {
15648                         mutex_exit(&mpt->m_mutex);
15649                         mptsas_log(mpt, CE_WARN,
15650                             "mptsas unable to get expander "
15651                             "parent device info for %x", page_address);
15652                         ndi_rtn = NDI_FAILURE;
15653                         goto smp_create_done;
15654                 }
15655 
15656                 smp_node->m_pdevhdl = dev_info.m_pdevhdl;
15657                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15658                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15659                     (uint32_t)dev_info.m_pdevhdl;
15660                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15661                     &dev_hdl, &sas_wwn, &smp_node->m_pdevinfo, &physport,
15662                     &phy_id, &pdev_hdl, &bay_num, &enclosure, &io_flags);
15663                 if (rval != DDI_SUCCESS) {
15664                         mutex_exit(&mpt->m_mutex);
15665                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15666                             "device info for %x", page_address);
15667                         ndi_rtn = NDI_FAILURE;
15668                         goto smp_create_done;
15669                 }
15670 
15671                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_HANDLE &
15672                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) |
15673                     (uint32_t)dev_info.m_devhdl;
15674                 rval = mptsas_get_sas_device_page0(mpt, page_address,
15675                     &dev_hdl, &smp_sas_wwn, &smp_node->m_deviceinfo,
15676                     &physport, &phy_id, &pdev_hdl, &bay_num, &enclosure,
15677                     &io_flags);
15678                 if (rval != DDI_SUCCESS) {
15679                         mutex_exit(&mpt->m_mutex);
15680                         mptsas_log(mpt, CE_WARN, "mptsas unable to get "
15681                             "device info for %x", page_address);
15682                         ndi_rtn = NDI_FAILURE;
15683                         goto smp_create_done;
15684                 }
15685                 mutex_exit(&mpt->m_mutex);
15686 
15687                 /*
15688                  * If this smp direct attached to the controller
15689                  * set the attached-port to the base wwid
15690                  */
15691                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15692                     != DEVINFO_DIRECT_ATTACHED) {
15693                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15694                             sas_wwn);
15695                 } else {
15696                         (void) sprintf(attached_wwn_str, "w%016"PRIx64,
15697                             mpt->un.m_base_wwid);
15698                 }
15699 
15700                 if (ndi_prop_update_string(DDI_DEV_T_NONE,
15701                     *smp_dip, SCSI_ADDR_PROP_ATTACHED_PORT, attached_wwn_str) !=
15702                     DDI_PROP_SUCCESS) {
15703                         mptsas_log(mpt, CE_WARN, "mptsas unable to create "
15704                             "property for smp attached-port %s (sas_wwn)",
15705                             attached_wwn_str);
15706                         ndi_rtn = NDI_FAILURE;
15707                         goto smp_create_done;
15708                 }
15709 
15710                 if (ndi_prop_create_boolean(DDI_DEV_T_NONE,
15711                     *smp_dip, SMP_PROP) != DDI_PROP_SUCCESS) {
15712                         mptsas_log(mpt, CE_WARN, "mptsas unable to "
15713                             "create property for SMP %s (SMP_PROP) ",
15714                             wwn_str);
15715                         ndi_rtn = NDI_FAILURE;
15716                         goto smp_create_done;
15717                 }
15718 
15719                 /*
15720                  * check the smp to see whether it direct
15721                  * attached to the controller
15722                  */
15723                 if ((smp_node->m_deviceinfo & DEVINFO_DIRECT_ATTACHED)
15724                     != DEVINFO_DIRECT_ATTACHED) {
15725                         goto smp_create_done;
15726                 }
15727                 numphys = ddi_prop_get_int(DDI_DEV_T_ANY, pdip,
15728                     DDI_PROP_DONTPASS, MPTSAS_NUM_PHYS, -1);
15729                 if (numphys > 0) {
15730                         goto smp_create_done;
15731                 }
15732                 /*
15733                  * this iport is an old iport, we need to
15734                  * reconfig the props for it.
15735                  */
15736                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15737                     MPTSAS_VIRTUAL_PORT, 0) !=
15738                     DDI_PROP_SUCCESS) {
15739                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15740                             MPTSAS_VIRTUAL_PORT);
15741                         mptsas_log(mpt, CE_WARN, "mptsas virtual port "
15742                             "prop update failed");
15743                         goto smp_create_done;
15744                 }
15745 
15746                 mutex_enter(&mpt->m_mutex);
15747                 numphys = 0;
15748                 iport = ddi_get_name_addr(pdip);
15749                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15750                         bzero(phymask, sizeof (phymask));
15751                         (void) sprintf(phymask,
15752                             "%x", mpt->m_phy_info[i].phy_mask);
15753                         if (strcmp(phymask, iport) == 0) {
15754                                 phy_mask = mpt->m_phy_info[i].phy_mask;
15755                                 break;
15756                         }
15757                 }
15758 
15759                 for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15760                         if ((phy_mask >> i) & 0x01) {
15761                                 numphys++;
15762                         }
15763                 }
15764                 /*
15765                  * Update PHY info for smhba
15766                  */
15767                 if (mptsas_smhba_phy_init(mpt)) {
15768                         mutex_exit(&mpt->m_mutex);
15769                         mptsas_log(mpt, CE_WARN, "mptsas phy update "
15770                             "failed");
15771                         goto smp_create_done;
15772                 }
15773                 mutex_exit(&mpt->m_mutex);
15774 
15775                 mptsas_smhba_set_all_phy_props(mpt, pdip, numphys, phy_mask,
15776                     &attached_devhdl);
15777 
15778                 if (ddi_prop_update_int(DDI_DEV_T_NONE, pdip,
15779                     MPTSAS_NUM_PHYS, numphys) !=
15780                     DDI_PROP_SUCCESS) {
15781                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15782                             MPTSAS_NUM_PHYS);
15783                         mptsas_log(mpt, CE_WARN, "mptsas update "
15784                             "num phys props failed");
15785                         goto smp_create_done;
15786                 }
15787                 /*
15788                  * Add parent's props for SMHBA support
15789                  */
15790                 if (ddi_prop_update_string(DDI_DEV_T_NONE, pdip,
15791                     SCSI_ADDR_PROP_ATTACHED_PORT, wwn_str) !=
15792                     DDI_PROP_SUCCESS) {
15793                         (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip,
15794                             SCSI_ADDR_PROP_ATTACHED_PORT);
15795                         mptsas_log(mpt, CE_WARN, "mptsas update iport"
15796                             "attached-port failed");
15797                         goto smp_create_done;
15798                 }
15799 
15800 smp_create_done:
15801                 /*
15802                  * If props were setup ok, online the lun
15803                  */
15804                 if (ndi_rtn == NDI_SUCCESS) {
15805                         /*
15806                          * Try to online the new node
15807                          */
15808                         ndi_rtn = ndi_devi_online(*smp_dip, NDI_ONLINE_ATTACH);
15809                 }
15810 
15811                 /*
15812                  * If success set rtn flag, else unwire alloc'd lun
15813                  */
15814                 if (ndi_rtn != NDI_SUCCESS) {
15815                         NDBG12(("mptsas unable to online "
15816                             "SMP target %s", wwn_str));
15817                         ndi_prop_remove_all(*smp_dip);
15818                         (void) ndi_devi_free(*smp_dip);
15819                 }
15820         }
15821 
15822         return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
15823 }
15824 
15825 /* smp transport routine */
15826 static int mptsas_smp_start(struct smp_pkt *smp_pkt)
15827 {
15828         uint64_t                        wwn;
15829         Mpi2SmpPassthroughRequest_t     req;
15830         Mpi2SmpPassthroughReply_t       rep;
15831         uint32_t                        direction = 0;
15832         mptsas_t                        *mpt;
15833         int                             ret;
15834         uint64_t                        tmp64;
15835 
15836         mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
15837             smp_a_hba_tran->smp_tran_hba_private;
15838 
15839         bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
15840         /*
15841          * Need to compose a SMP request message
15842          * and call mptsas_do_passthru() function
15843          */
15844         bzero(&req, sizeof (req));
15845         bzero(&rep, sizeof (rep));
15846         req.PassthroughFlags = 0;
15847         req.PhysicalPort = 0xff;
15848         req.ChainOffset = 0;
15849         req.Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
15850 
15851         if ((smp_pkt->smp_pkt_reqsize & 0xffff0000ul) != 0) {
15852                 smp_pkt->smp_pkt_reason = ERANGE;
15853                 return (DDI_FAILURE);
15854         }
15855         req.RequestDataLength = LE_16((uint16_t)(smp_pkt->smp_pkt_reqsize - 4));
15856 
15857         req.MsgFlags = 0;
15858         tmp64 = LE_64(wwn);
15859         bcopy(&tmp64, &req.SASAddress, SAS_WWN_BYTE_SIZE);
15860         if (smp_pkt->smp_pkt_rspsize > 0) {
15861                 direction |= MPTSAS_PASS_THRU_DIRECTION_READ;
15862         }
15863         if (smp_pkt->smp_pkt_reqsize > 0) {
15864                 direction |= MPTSAS_PASS_THRU_DIRECTION_WRITE;
15865         }
15866 
15867         mutex_enter(&mpt->m_mutex);
15868         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep,
15869             (uint8_t *)smp_pkt->smp_pkt_rsp,
15870             offsetof(Mpi2SmpPassthroughRequest_t, SGL), sizeof (rep),
15871             smp_pkt->smp_pkt_rspsize - 4, direction,
15872             (uint8_t *)smp_pkt->smp_pkt_req, smp_pkt->smp_pkt_reqsize - 4,
15873             smp_pkt->smp_pkt_timeout, FKIOCTL);
15874         mutex_exit(&mpt->m_mutex);
15875         if (ret != 0) {
15876                 cmn_err(CE_WARN, "smp_start do passthru error %d", ret);
15877                 smp_pkt->smp_pkt_reason = (uchar_t)(ret);
15878                 return (DDI_FAILURE);
15879         }
15880         /* do passthrough success, check the smp status */
15881         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
15882                 switch (LE_16(rep.IOCStatus)) {
15883                 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
15884                         smp_pkt->smp_pkt_reason = ENODEV;
15885                         break;
15886                 case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
15887                         smp_pkt->smp_pkt_reason = EOVERFLOW;
15888                         break;
15889                 case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
15890                         smp_pkt->smp_pkt_reason = EIO;
15891                         break;
15892                 default:
15893                         mptsas_log(mpt, CE_NOTE, "smp_start: get unknown ioc"
15894                             "status:%x", LE_16(rep.IOCStatus));
15895                         smp_pkt->smp_pkt_reason = EIO;
15896                         break;
15897                 }
15898                 return (DDI_FAILURE);
15899         }
15900         if (rep.SASStatus != MPI2_SASSTATUS_SUCCESS) {
15901                 mptsas_log(mpt, CE_NOTE, "smp_start: get error SAS status:%x",
15902                     rep.SASStatus);
15903                 smp_pkt->smp_pkt_reason = EIO;
15904                 return (DDI_FAILURE);
15905         }
15906 
15907         return (DDI_SUCCESS);
15908 }
15909 
15910 /*
15911  * If we didn't get a match, we need to get sas page0 for each device, and
15912  * untill we get a match. If failed, return NULL
15913  */
15914 static mptsas_target_t *
15915 mptsas_phy_to_tgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint8_t phy)
15916 {
15917         int             i, j = 0;
15918         int             rval = 0;
15919         uint16_t        cur_handle;
15920         uint32_t        page_address;
15921         mptsas_target_t *ptgt = NULL;
15922 
15923         /*
15924          * PHY named device must be direct attached and attaches to
15925          * narrow port, if the iport is not parent of the device which
15926          * we are looking for.
15927          */
15928         for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
15929                 if ((1 << i) & phymask)
15930                         j++;
15931         }
15932 
15933         if (j > 1)
15934                 return (NULL);
15935 
15936         /*
15937          * Must be a narrow port and single device attached to the narrow port
15938          * So the physical port num of device  which is equal to the iport's
15939          * port num is the device what we are looking for.
15940          */
15941 
15942         if (mpt->m_phy_info[phy].phy_mask != phymask)
15943                 return (NULL);
15944 
15945         mutex_enter(&mpt->m_mutex);
15946 
15947         ptgt = refhash_linear_search(mpt->m_targets, mptsas_target_eval_nowwn,
15948             &phy);
15949         if (ptgt != NULL) {
15950                 mutex_exit(&mpt->m_mutex);
15951                 return (ptgt);
15952         }
15953 
15954         if (mpt->m_done_traverse_dev) {
15955                 mutex_exit(&mpt->m_mutex);
15956                 return (NULL);
15957         }
15958 
15959         /* If didn't get a match, come here */
15960         cur_handle = mpt->m_dev_handle;
15961         for (; ; ) {
15962                 ptgt = NULL;
15963                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
15964                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | (uint32_t)cur_handle;
15965                 rval = mptsas_get_target_device_info(mpt, page_address,
15966                     &cur_handle, &ptgt);
15967                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
15968                     (rval == DEV_INFO_FAIL_ALLOC)) {
15969                         break;
15970                 }
15971                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
15972                     (rval == DEV_INFO_PHYS_DISK)) {
15973                         continue;
15974                 }
15975                 mpt->m_dev_handle = cur_handle;
15976 
15977                 if ((ptgt->m_addr.mta_wwn == 0) && (ptgt->m_phynum == phy)) {
15978                         break;
15979                 }
15980         }
15981 
15982         mutex_exit(&mpt->m_mutex);
15983         return (ptgt);
15984 }
15985 
15986 /*
15987  * The ptgt->m_addr.mta_wwn contains the wwid for each disk.
15988  * For Raid volumes, we need to check m_raidvol[x].m_raidwwid
15989  * If we didn't get a match, we need to get sas page0 for each device, and
15990  * untill we get a match
15991  * If failed, return NULL
15992  */
15993 static mptsas_target_t *
15994 mptsas_wwid_to_ptgt(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
15995 {
15996         int             rval = 0;
15997         uint16_t        cur_handle;
15998         uint32_t        page_address;
15999         mptsas_target_t *tmp_tgt = NULL;
16000         mptsas_target_addr_t addr;
16001 
16002         addr.mta_wwn = wwid;
16003         addr.mta_phymask = phymask;
16004         mutex_enter(&mpt->m_mutex);
16005         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16006         if (tmp_tgt != NULL) {
16007                 mutex_exit(&mpt->m_mutex);
16008                 return (tmp_tgt);
16009         }
16010 
16011         if (phymask == 0) {
16012                 /*
16013                  * It's IR volume
16014                  */
16015                 rval = mptsas_get_raid_info(mpt);
16016                 if (rval) {
16017                         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16018                 }
16019                 mutex_exit(&mpt->m_mutex);
16020                 return (tmp_tgt);
16021         }
16022 
16023         if (mpt->m_done_traverse_dev) {
16024                 mutex_exit(&mpt->m_mutex);
16025                 return (NULL);
16026         }
16027 
16028         /* If didn't get a match, come here */
16029         cur_handle = mpt->m_dev_handle;
16030         for (;;) {
16031                 tmp_tgt = NULL;
16032                 page_address = (MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE &
16033                     MPI2_SAS_DEVICE_PGAD_FORM_MASK) | cur_handle;
16034                 rval = mptsas_get_target_device_info(mpt, page_address,
16035                     &cur_handle, &tmp_tgt);
16036                 if ((rval == DEV_INFO_FAIL_PAGE0) ||
16037                     (rval == DEV_INFO_FAIL_ALLOC)) {
16038                         tmp_tgt = NULL;
16039                         break;
16040                 }
16041                 if ((rval == DEV_INFO_WRONG_DEVICE_TYPE) ||
16042                     (rval == DEV_INFO_PHYS_DISK)) {
16043                         continue;
16044                 }
16045                 mpt->m_dev_handle = cur_handle;
16046                 if ((tmp_tgt->m_addr.mta_wwn) &&
16047                     (tmp_tgt->m_addr.mta_wwn == wwid) &&
16048                     (tmp_tgt->m_addr.mta_phymask == phymask)) {
16049                         break;
16050                 }
16051         }
16052 
16053         mutex_exit(&mpt->m_mutex);
16054         return (tmp_tgt);
16055 }
16056 
16057 static mptsas_smp_t *
16058 mptsas_wwid_to_psmp(mptsas_t *mpt, mptsas_phymask_t phymask, uint64_t wwid)
16059 {
16060         int             rval = 0;
16061         uint16_t        cur_handle;
16062         uint32_t        page_address;
16063         mptsas_smp_t    smp_node, *psmp = NULL;
16064         mptsas_target_addr_t addr;
16065 
16066         addr.mta_wwn = wwid;
16067         addr.mta_phymask = phymask;
16068         mutex_enter(&mpt->m_mutex);
16069         psmp = refhash_lookup(mpt->m_smp_targets, &addr);
16070         if (psmp != NULL) {
16071                 mutex_exit(&mpt->m_mutex);
16072                 return (psmp);
16073         }
16074 
16075         if (mpt->m_done_traverse_smp) {
16076                 mutex_exit(&mpt->m_mutex);
16077                 return (NULL);
16078         }
16079 
16080         /* If didn't get a match, come here */
16081         cur_handle = mpt->m_smp_devhdl;
16082         for (;;) {
16083                 psmp = NULL;
16084                 page_address = (MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL &
16085                     MPI2_SAS_EXPAND_PGAD_FORM_MASK) | (uint32_t)cur_handle;
16086                 rval = mptsas_get_sas_expander_page0(mpt, page_address,
16087                     &smp_node);
16088                 if (rval != DDI_SUCCESS) {
16089                         break;
16090                 }
16091                 mpt->m_smp_devhdl = cur_handle = smp_node.m_devhdl;
16092                 psmp = mptsas_smp_alloc(mpt, &smp_node);
16093                 ASSERT(psmp);
16094                 if ((psmp->m_addr.mta_wwn) && (psmp->m_addr.mta_wwn == wwid) &&
16095                     (psmp->m_addr.mta_phymask == phymask)) {
16096                         break;
16097                 }
16098         }
16099 
16100         mutex_exit(&mpt->m_mutex);
16101         return (psmp);
16102 }
16103 
16104 mptsas_target_t *
16105 mptsas_tgt_alloc(mptsas_t *mpt, uint16_t devhdl, uint64_t wwid,
16106     uint32_t devinfo, mptsas_phymask_t phymask, uint8_t phynum)
16107 {
16108         mptsas_target_t *tmp_tgt = NULL;
16109         mptsas_target_addr_t addr;
16110 
16111         addr.mta_wwn = wwid;
16112         addr.mta_phymask = phymask;
16113         tmp_tgt = refhash_lookup(mpt->m_targets, &addr);
16114         if (tmp_tgt != NULL) {
16115                 NDBG20(("Hash item already exist"));
16116                 tmp_tgt->m_deviceinfo = devinfo;
16117                 tmp_tgt->m_devhdl = devhdl;  /* XXX - duplicate? */
16118                 return (tmp_tgt);
16119         }
16120         tmp_tgt = kmem_zalloc(sizeof (struct mptsas_target), KM_SLEEP);
16121         if (tmp_tgt == NULL) {
16122                 cmn_err(CE_WARN, "Fatal, allocated tgt failed");
16123                 return (NULL);
16124         }
16125         tmp_tgt->m_devhdl = devhdl;
16126         tmp_tgt->m_addr.mta_wwn = wwid;
16127         tmp_tgt->m_deviceinfo = devinfo;
16128         tmp_tgt->m_addr.mta_phymask = phymask;
16129         tmp_tgt->m_phynum = phynum;
16130         /* Initialized the tgt structure */
16131         tmp_tgt->m_qfull_retries = QFULL_RETRIES;
16132         tmp_tgt->m_qfull_retry_interval =
16133             drv_usectohz(QFULL_RETRY_INTERVAL * 1000);
16134         tmp_tgt->m_t_throttle = MAX_THROTTLE;
16135         TAILQ_INIT(&tmp_tgt->m_active_cmdq);
16136 
16137         refhash_insert(mpt->m_targets, tmp_tgt);
16138 
16139         return (tmp_tgt);
16140 }
16141 
16142 static void
16143 mptsas_smp_target_copy(mptsas_smp_t *src, mptsas_smp_t *dst)
16144 {
16145         dst->m_devhdl = src->m_devhdl;
16146         dst->m_deviceinfo = src->m_deviceinfo;
16147         dst->m_pdevhdl = src->m_pdevhdl;
16148         dst->m_pdevinfo = src->m_pdevinfo;
16149 }
16150 
16151 static mptsas_smp_t *
16152 mptsas_smp_alloc(mptsas_t *mpt, mptsas_smp_t *data)
16153 {
16154         mptsas_target_addr_t addr;
16155         mptsas_smp_t *ret_data;
16156 
16157         addr.mta_wwn = data->m_addr.mta_wwn;
16158         addr.mta_phymask = data->m_addr.mta_phymask;
16159         ret_data = refhash_lookup(mpt->m_smp_targets, &addr);
16160         /*
16161          * If there's already a matching SMP target, update its fields
16162          * in place.  Since the address is not changing, it's safe to do
16163          * this.  We cannot just bcopy() here because the structure we've
16164          * been given has invalid hash links.
16165          */
16166         if (ret_data != NULL) {
16167                 mptsas_smp_target_copy(data, ret_data);
16168                 return (ret_data);
16169         }
16170 
16171         ret_data = kmem_alloc(sizeof (mptsas_smp_t), KM_SLEEP);
16172         bcopy(data, ret_data, sizeof (mptsas_smp_t));
16173         refhash_insert(mpt->m_smp_targets, ret_data);
16174         return (ret_data);
16175 }
16176 
16177 /*
16178  * Functions for SGPIO LED support
16179  */
16180 static dev_info_t *
16181 mptsas_get_dip_from_dev(dev_t dev, mptsas_phymask_t *phymask)
16182 {
16183         dev_info_t      *dip;
16184         int             prop;
16185         dip = e_ddi_hold_devi_by_dev(dev, 0);
16186         if (dip == NULL)
16187                 return (dip);
16188         prop = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
16189             "phymask", 0);
16190         *phymask = (mptsas_phymask_t)prop;
16191         ddi_release_devi(dip);
16192         return (dip);
16193 }
16194 static mptsas_target_t *
16195 mptsas_addr_to_ptgt(mptsas_t *mpt, char *addr, mptsas_phymask_t phymask)
16196 {
16197         uint8_t                 phynum;
16198         uint64_t                wwn;
16199         int                     lun;
16200         mptsas_target_t         *ptgt = NULL;
16201 
16202         if (mptsas_parse_address(addr, &wwn, &phynum, &lun) != DDI_SUCCESS) {
16203                 return (NULL);
16204         }
16205         if (addr[0] == 'w') {
16206                 ptgt = mptsas_wwid_to_ptgt(mpt, (int)phymask, wwn);
16207         } else {
16208                 ptgt = mptsas_phy_to_tgt(mpt, (int)phymask, phynum);
16209         }
16210         return (ptgt);
16211 }
16212 
16213 static int
16214 mptsas_flush_led_status(mptsas_t *mpt, mptsas_target_t *ptgt)
16215 {
16216         uint32_t slotstatus = 0;
16217 
16218         /* Build an MPI2 Slot Status based on our view of the world */
16219         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_IDENT - 1)))
16220                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST;
16221         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_FAIL - 1)))
16222                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
16223         if (ptgt->m_led_status & (1 << (MPTSAS_LEDCTL_LED_OK2RM - 1)))
16224                 slotstatus |= MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE;
16225 
16226         /* Write it to the controller */
16227         NDBG14(("mptsas_ioctl: set LED status %x for slot %x",
16228             slotstatus, ptgt->m_slot_num));
16229         return (mptsas_send_sep(mpt, ptgt, &slotstatus,
16230             MPI2_SEP_REQ_ACTION_WRITE_STATUS));
16231 }
16232 
16233 /*
16234  *  send sep request, use enclosure/slot addressing
16235  */
16236 static int
16237 mptsas_send_sep(mptsas_t *mpt, mptsas_target_t *ptgt,
16238     uint32_t *status, uint8_t act)
16239 {
16240         Mpi2SepRequest_t        req;
16241         Mpi2SepReply_t          rep;
16242         int                     ret;
16243 
16244         ASSERT(mutex_owned(&mpt->m_mutex));
16245 
16246         /*
16247          * We only support SEP control of directly-attached targets, in which
16248          * case the "SEP" we're talking to is a virtual one contained within
16249          * the HBA itself.  This is necessary because DA targets typically have
16250          * no other mechanism for LED control.  Targets for which a separate
16251          * enclosure service processor exists should be controlled via ses(7d)
16252          * or sgen(7d).  Furthermore, since such requests can time out, they
16253          * should be made in user context rather than in response to
16254          * asynchronous fabric changes.
16255          *
16256          * In addition, we do not support this operation for RAID volumes,
16257          * since there is no slot associated with them.
16258          */
16259         if (!(ptgt->m_deviceinfo & DEVINFO_DIRECT_ATTACHED) ||
16260             ptgt->m_addr.mta_phymask == 0) {
16261                 return (ENOTTY);
16262         }
16263 
16264         bzero(&req, sizeof (req));
16265         bzero(&rep, sizeof (rep));
16266 
16267         req.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
16268         req.Action = act;
16269         req.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
16270         req.EnclosureHandle = LE_16(ptgt->m_enclosure);
16271         req.Slot = LE_16(ptgt->m_slot_num);
16272         if (act == MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16273                 req.SlotStatus = LE_32(*status);
16274         }
16275         ret = mptsas_do_passthru(mpt, (uint8_t *)&req, (uint8_t *)&rep, NULL,
16276             sizeof (req), sizeof (rep), NULL, 0, NULL, 0, 60, FKIOCTL);
16277         if (ret != 0) {
16278                 mptsas_log(mpt, CE_NOTE, "mptsas_send_sep: passthru SEP "
16279                     "Processor Request message error %d", ret);
16280                 return (ret);
16281         }
16282         /* do passthrough success, check the ioc status */
16283         if (LE_16(rep.IOCStatus) != MPI2_IOCSTATUS_SUCCESS) {
16284                 mptsas_log(mpt, CE_NOTE, "send_sep act %x: ioc "
16285                     "status:%x loginfo %x", act, LE_16(rep.IOCStatus),
16286                     LE_32(rep.IOCLogInfo));
16287                 switch (LE_16(rep.IOCStatus) & MPI2_IOCSTATUS_MASK) {
16288                 case MPI2_IOCSTATUS_INVALID_FUNCTION:
16289                 case MPI2_IOCSTATUS_INVALID_VPID:
16290                 case MPI2_IOCSTATUS_INVALID_FIELD:
16291                 case MPI2_IOCSTATUS_INVALID_STATE:
16292                 case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
16293                 case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
16294                 case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
16295                 case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
16296                 case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
16297                 case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
16298                         return (EINVAL);
16299                 case MPI2_IOCSTATUS_BUSY:
16300                         return (EBUSY);
16301                 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
16302                         return (EAGAIN);
16303                 case MPI2_IOCSTATUS_INVALID_SGL:
16304                 case MPI2_IOCSTATUS_INTERNAL_ERROR:
16305                 case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
16306                 default:
16307                         return (EIO);
16308                 }
16309         }
16310         if (act != MPI2_SEP_REQ_ACTION_WRITE_STATUS) {
16311                 *status = LE_32(rep.SlotStatus);
16312         }
16313 
16314         return (0);
16315 }
16316 
16317 int
16318 mptsas_dma_addr_create(mptsas_t *mpt, ddi_dma_attr_t dma_attr,
16319     ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp, caddr_t *dma_memp,
16320     uint32_t alloc_size, ddi_dma_cookie_t *cookiep)
16321 {
16322         ddi_dma_cookie_t        new_cookie;
16323         size_t                  alloc_len;
16324         uint_t                  ncookie;
16325 
16326         if (cookiep == NULL)
16327                 cookiep = &new_cookie;
16328 
16329         if (ddi_dma_alloc_handle(mpt->m_dip, &dma_attr, DDI_DMA_SLEEP,
16330             NULL, dma_hdp) != DDI_SUCCESS) {
16331                 return (FALSE);
16332         }
16333 
16334         if (ddi_dma_mem_alloc(*dma_hdp, alloc_size, &mpt->m_dev_acc_attr,
16335             DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, dma_memp, &alloc_len,
16336             acc_hdp) != DDI_SUCCESS) {
16337                 ddi_dma_free_handle(dma_hdp);
16338                 return (FALSE);
16339         }
16340 
16341         if (ddi_dma_addr_bind_handle(*dma_hdp, NULL, *dma_memp, alloc_len,
16342             (DDI_DMA_RDWR | DDI_DMA_CONSISTENT), DDI_DMA_SLEEP, NULL,
16343             cookiep, &ncookie) != DDI_DMA_MAPPED) {
16344                 (void) ddi_dma_mem_free(acc_hdp);
16345                 ddi_dma_free_handle(dma_hdp);
16346                 return (FALSE);
16347         }
16348 
16349         return (TRUE);
16350 }
16351 
16352 void
16353 mptsas_dma_addr_destroy(ddi_dma_handle_t *dma_hdp, ddi_acc_handle_t *acc_hdp)
16354 {
16355         if (*dma_hdp == NULL)
16356                 return;
16357 
16358         (void) ddi_dma_unbind_handle(*dma_hdp);
16359         (void) ddi_dma_mem_free(acc_hdp);
16360         ddi_dma_free_handle(dma_hdp);
16361 }