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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
  25  */
  26 
  27 /*
  28  * sf - Solaris Fibre Channel driver
  29  *
  30  * This module implements some of the Fibre Channel FC-4 layer, converting
  31  * from FC frames to SCSI and back.  (Note: no sequence management is done
  32  * here, though.)
  33  */
  34 
  35 #if defined(lint) && !defined(DEBUG)
  36 #define DEBUG   1
  37 #endif
  38 
  39 /*
  40  * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  41  * Need to use the ugly RAID LUN mappings in FCP Annex D
  42  * to prevent SCSA from barfing.  This *REALLY* needs to
  43  * be addressed by the standards committee.
  44  */
  45 #define RAID_LUNS       1
  46 
  47 #ifdef DEBUG
  48 static int sfdebug = 0;
  49 #include <sys/debug.h>
  50 
  51 #define SF_DEBUG(level, args) \
  52         if (sfdebug >= (level)) sf_log args
  53 #else
  54 #define SF_DEBUG(level, args)
  55 #endif
  56 
  57 static int sf_bus_config_debug = 0;
  58 
  59 /* Why do I have to do this? */
  60 #define offsetof(s, m)  (size_t)(&(((s *)0)->m))
  61 
  62 #include <sys/scsi/scsi.h>
  63 #include <sys/fc4/fcal.h>
  64 #include <sys/fc4/fcp.h>
  65 #include <sys/fc4/fcal_linkapp.h>
  66 #include <sys/socal_cq_defs.h>
  67 #include <sys/fc4/fcal_transport.h>
  68 #include <sys/fc4/fcio.h>
  69 #include <sys/scsi/adapters/sfvar.h>
  70 #include <sys/scsi/impl/scsi_reset_notify.h>
  71 #include <sys/stat.h>
  72 #include <sys/varargs.h>
  73 #include <sys/var.h>
  74 #include <sys/thread.h>
  75 #include <sys/proc.h>
  76 #include <sys/kstat.h>
  77 #include <sys/devctl.h>
  78 #include <sys/scsi/targets/ses.h>
  79 #include <sys/callb.h>
  80 
  81 static int sf_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
  82 static int sf_attach(dev_info_t *, ddi_attach_cmd_t);
  83 static int sf_detach(dev_info_t *, ddi_detach_cmd_t);
  84 static void sf_softstate_unlink(struct sf *);
  85 static int sf_scsi_bus_config(dev_info_t *parent, uint_t flag,
  86     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
  87 static int sf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
  88     ddi_bus_config_op_t op, void *arg);
  89 static int sf_scsi_tgt_init(dev_info_t *, dev_info_t *,
  90     scsi_hba_tran_t *, struct scsi_device *);
  91 static void sf_scsi_tgt_free(dev_info_t *, dev_info_t *,
  92     scsi_hba_tran_t *, struct scsi_device *);
  93 static int sf_pkt_alloc_extern(struct sf *, struct sf_pkt *,
  94     int, int, int);
  95 static void sf_pkt_destroy_extern(struct sf *, struct sf_pkt *);
  96 static struct scsi_pkt *sf_scsi_init_pkt(struct scsi_address *,
  97     struct scsi_pkt *, struct buf *, int, int, int, int, int (*)(), caddr_t);
  98 static void sf_scsi_destroy_pkt(struct scsi_address *, struct scsi_pkt *);
  99 static void sf_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
 100 static void sf_scsi_sync_pkt(struct scsi_address *, struct scsi_pkt *);
 101 static int sf_scsi_reset_notify(struct scsi_address *, int,
 102     void (*)(caddr_t), caddr_t);
 103 static int sf_scsi_get_name(struct scsi_device *, char *, int);
 104 static int sf_scsi_get_bus_addr(struct scsi_device *, char *, int);
 105 static int sf_add_cr_pool(struct sf *);
 106 static int sf_cr_alloc(struct sf *, struct sf_pkt *, int (*)());
 107 static void sf_cr_free(struct sf_cr_pool *, struct sf_pkt *);
 108 static void sf_crpool_free(struct sf *);
 109 static int sf_kmem_cache_constructor(void *, void *, int);
 110 static void sf_kmem_cache_destructor(void *, void *);
 111 static void sf_statec_callback(void *, int);
 112 static int sf_login(struct sf *, uchar_t, uchar_t, uint_t, int);
 113 static int sf_els_transport(struct sf *, struct sf_els_hdr *);
 114 static void sf_els_callback(struct fcal_packet *);
 115 static int sf_do_prli(struct sf *, struct sf_els_hdr *, struct la_els_logi *);
 116 static int sf_do_adisc(struct sf *, struct sf_els_hdr *);
 117 static int sf_do_reportlun(struct sf *, struct sf_els_hdr *,
 118     struct sf_target *);
 119 static void sf_reportlun_callback(struct fcal_packet *);
 120 static int sf_do_inquiry(struct sf *, struct sf_els_hdr *,
 121     struct sf_target *);
 122 static void sf_inq_callback(struct fcal_packet *);
 123 static struct fcal_packet *sf_els_alloc(struct sf *, uchar_t, int, int,
 124     int, caddr_t *, caddr_t *);
 125 static void sf_els_free(struct fcal_packet *);
 126 static struct sf_target *sf_create_target(struct sf *,
 127     struct sf_els_hdr *, int, int64_t);
 128 #ifdef RAID_LUNS
 129 static struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int);
 130 #else
 131 static struct sf_target *sf_lookup_target(struct sf *, uchar_t *, int64_t);
 132 #endif
 133 static void sf_finish_init(struct sf *, int);
 134 static void sf_offline_target(struct sf *, struct sf_target *);
 135 static void sf_create_devinfo(struct sf *, struct sf_target *, int);
 136 static int sf_create_props(dev_info_t *, struct sf_target *, int);
 137 static int sf_commoncap(struct scsi_address *, char *, int, int, int);
 138 static int sf_getcap(struct scsi_address *, char *, int);
 139 static int sf_setcap(struct scsi_address *, char *, int, int);
 140 static int sf_abort(struct scsi_address *, struct scsi_pkt *);
 141 static int sf_reset(struct scsi_address *, int);
 142 static void sf_abort_all(struct sf *, struct sf_target *, int, int, int);
 143 static int sf_start(struct scsi_address *, struct scsi_pkt *);
 144 static int sf_start_internal(struct sf *, struct sf_pkt *);
 145 static void sf_fill_ids(struct sf *, struct sf_pkt *, struct sf_target *);
 146 static int sf_prepare_pkt(struct sf *, struct sf_pkt *, struct sf_target *);
 147 static int sf_dopoll(struct sf *, struct sf_pkt *);
 148 static void sf_cmd_callback(struct fcal_packet *);
 149 static void sf_throttle(struct sf *);
 150 static void sf_watch(void *);
 151 static void sf_throttle_start(struct sf *);
 152 static void sf_check_targets(struct sf *);
 153 static void sf_check_reset_delay(void *);
 154 static int sf_target_timeout(struct sf *, struct sf_pkt *);
 155 static void sf_force_lip(struct sf *);
 156 static void sf_unsol_els_callback(void *, soc_response_t *, caddr_t);
 157 static struct sf_els_hdr *sf_els_timeout(struct sf *, struct sf_els_hdr *);
 158 /*PRINTFLIKE3*/
 159 static void sf_log(struct sf *, int, const char *, ...);
 160 static int sf_kstat_update(kstat_t *, int);
 161 static int sf_open(dev_t *, int, int, cred_t *);
 162 static int sf_close(dev_t, int, int, cred_t *);
 163 static int sf_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 164 static struct sf_target *sf_get_target_from_dip(struct sf *, dev_info_t *);
 165 static int sf_bus_get_eventcookie(dev_info_t *, dev_info_t *, char *,
 166     ddi_eventcookie_t *);
 167 static int sf_bus_add_eventcall(dev_info_t *, dev_info_t *,
 168     ddi_eventcookie_t, void (*)(), void *, ddi_callback_id_t *cb_id);
 169 static int sf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id);
 170 static int sf_bus_post_event(dev_info_t *, dev_info_t *,
 171     ddi_eventcookie_t, void *);
 172 
 173 static void sf_hp_daemon(void *);
 174 
 175 /*
 176  * this is required to be able to supply a control node
 177  * where ioctls can be executed
 178  */
 179 struct cb_ops sf_cb_ops = {
 180         sf_open,                        /* open */
 181         sf_close,                       /* close */
 182         nodev,                          /* strategy */
 183         nodev,                          /* print */
 184         nodev,                          /* dump */
 185         nodev,                          /* read */
 186         nodev,                          /* write */
 187         sf_ioctl,                       /* ioctl */
 188         nodev,                          /* devmap */
 189         nodev,                          /* mmap */
 190         nodev,                          /* segmap */
 191         nochpoll,                       /* poll */
 192         ddi_prop_op,                    /* cb_prop_op */
 193         0,                              /* streamtab  */
 194         D_MP | D_NEW | D_HOTPLUG        /* driver flags */
 195 
 196 };
 197 
 198 /*
 199  * autoconfiguration routines.
 200  */
 201 static struct dev_ops sf_ops = {
 202         DEVO_REV,               /* devo_rev, */
 203         0,                      /* refcnt  */
 204         sf_info,                /* info */
 205         nulldev,                /* identify */
 206         nulldev,                /* probe */
 207         sf_attach,              /* attach */
 208         sf_detach,              /* detach */
 209         nodev,                  /* reset */
 210         &sf_cb_ops,         /* driver operations */
 211         NULL,                   /* bus operations */
 212         NULL,                   /* power management */
 213         ddi_quiesce_not_supported,      /* devo_quiesce */
 214 };
 215 
 216 #define SF_NAME "FC-AL FCP Nexus Driver"        /* Name of the module. */
 217 static  char    sf_version[] = "1.72 08/19/2008"; /* version of the module */
 218 
 219 static struct modldrv modldrv = {
 220         &mod_driverops, /* Type of module. This one is a driver */
 221         SF_NAME,
 222         &sf_ops,    /* driver ops */
 223 };
 224 
 225 static struct modlinkage modlinkage = {
 226         MODREV_1, (void *)&modldrv, NULL
 227 };
 228 
 229 /* XXXXXX The following is here to handle broken targets -- remove it later */
 230 static int sf_reportlun_forever = 0;
 231 /* XXXXXX */
 232 static int sf_lip_on_plogo = 0;
 233 static int sf_els_retries = SF_ELS_RETRIES;
 234 static struct sf *sf_head = NULL;
 235 static int sf_target_scan_cnt = 4;
 236 static int sf_pkt_scan_cnt = 5;
 237 static int sf_pool_scan_cnt = 1800;
 238 static void *sf_state = NULL;
 239 static int sf_watchdog_init = 0;
 240 static int sf_watchdog_time = 0;
 241 static int sf_watchdog_timeout = 1;
 242 static int sf_watchdog_tick;
 243 static int sf_watch_running = 0;
 244 static timeout_id_t sf_watchdog_id;
 245 static timeout_id_t sf_reset_timeout_id;
 246 static int sf_max_targets = SF_MAX_TARGETS;
 247 static kmutex_t sf_global_mutex;
 248 static int sf_core = 0;
 249 int *sf_token = NULL; /* Must not be static or lint complains. */
 250 static kcondvar_t sf_watch_cv;
 251 extern pri_t minclsyspri;
 252 static ddi_eventcookie_t        sf_insert_eid;
 253 static ddi_eventcookie_t        sf_remove_eid;
 254 
 255 static ndi_event_definition_t   sf_event_defs[] = {
 256 { SF_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL, 0 },
 257 { SF_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT, 0 }
 258 };
 259 
 260 #define SF_N_NDI_EVENTS \
 261         (sizeof (sf_event_defs) / sizeof (ndi_event_definition_t))
 262 
 263 #ifdef DEBUG
 264 static int sf_lip_flag = 1;             /* bool: to allow LIPs */
 265 static int sf_reset_flag = 1;           /* bool: to allow reset after LIP */
 266 static int sf_abort_flag = 0;           /* bool: to do just one abort */
 267 #endif
 268 
 269 extern int64_t ddi_get_lbolt64(void);
 270 
 271 /*
 272  * for converting between target number (switch) and hard address/AL_PA
 273  */
 274 static uchar_t sf_switch_to_alpa[] = {
 275         0xef, 0xe8, 0xe4, 0xe2, 0xe1, 0xe0, 0xdc, 0xda, 0xd9, 0xd6,
 276         0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xce, 0xcd, 0xcc, 0xcb, 0xca,
 277         0xc9, 0xc7, 0xc6, 0xc5, 0xc3, 0xbc, 0xba, 0xb9, 0xb6, 0xb5,
 278         0xb4, 0xb3, 0xb2, 0xb1, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9,
 279         0xa7, 0xa6, 0xa5, 0xa3, 0x9f, 0x9e, 0x9d, 0x9b, 0x98, 0x97,
 280         0x90, 0x8f, 0x88, 0x84, 0x82, 0x81, 0x80, 0x7c, 0x7a, 0x79,
 281         0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x6e, 0x6d, 0x6c, 0x6b,
 282         0x6a, 0x69, 0x67, 0x66, 0x65, 0x63, 0x5c, 0x5a, 0x59, 0x56,
 283         0x55, 0x54, 0x53, 0x52, 0x51, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a,
 284         0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, 0x3a, 0x39, 0x36, 0x35,
 285         0x34, 0x33, 0x32, 0x31, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29,
 286         0x27, 0x26, 0x25, 0x23, 0x1f, 0x1e, 0x1d, 0x1b, 0x18, 0x17,
 287         0x10, 0x0f, 0x08, 0x04, 0x02, 0x01
 288 };
 289 
 290 static uchar_t sf_alpa_to_switch[] = {
 291         0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
 292         0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
 293         0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
 294         0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
 295         0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
 296         0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
 297         0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
 298         0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
 299         0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
 300         0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
 301         0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
 302         0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
 303         0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
 304         0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
 305         0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
 306         0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
 307         0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
 308         0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
 309         0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
 310         0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
 311         0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
 312         0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
 313         0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
 314         0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 315 };
 316 
 317 /*
 318  * these macros call the proper transport-layer function given
 319  * a particular transport
 320  */
 321 #define soc_transport(a, b, c, d) (*a->fcal_ops->fcal_transport)(b, c, d)
 322 #define soc_transport_poll(a, b, c, d)\
 323         (*a->fcal_ops->fcal_transport_poll)(b, c, d)
 324 #define soc_get_lilp_map(a, b, c, d, e)\
 325         (*a->fcal_ops->fcal_lilp_map)(b, c, d, e)
 326 #define soc_force_lip(a, b, c, d, e)\
 327         (*a->fcal_ops->fcal_force_lip)(b, c, d, e)
 328 #define soc_abort(a, b, c, d, e)\
 329         (*a->fcal_ops->fcal_abort_cmd)(b, c, d, e)
 330 #define soc_force_reset(a, b, c, d)\
 331         (*a->fcal_ops->fcal_force_reset)(b, c, d)
 332 #define soc_add_ulp(a, b, c, d, e, f, g, h)\
 333         (*a->fcal_ops->fcal_add_ulp)(b, c, d, e, f, g, h)
 334 #define soc_remove_ulp(a, b, c, d, e)\
 335         (*a->fcal_ops->fcal_remove_ulp)(b, c, d, e)
 336 #define soc_take_core(a, b) (*a->fcal_ops->fcal_take_core)(b)
 337 
 338 
 339 /* power management property defines (should be in a common include file?) */
 340 #define PM_HARDWARE_STATE_PROP          "pm-hardware-state"
 341 #define PM_NEEDS_SUSPEND_RESUME         "needs-suspend-resume"
 342 
 343 
 344 /* node properties */
 345 #define NODE_WWN_PROP                   "node-wwn"
 346 #define PORT_WWN_PROP                   "port-wwn"
 347 #define LIP_CNT_PROP                    "lip-count"
 348 #define TARGET_PROP                     "target"
 349 #define LUN_PROP                        "lun"
 350 
 351 
 352 /*
 353  * initialize this driver and install this module
 354  */
 355 int
 356 _init(void)
 357 {
 358         int     i;
 359 
 360         i = ddi_soft_state_init(&sf_state, sizeof (struct sf),
 361             SF_INIT_ITEMS);
 362         if (i != 0)
 363                 return (i);
 364 
 365         if ((i = scsi_hba_init(&modlinkage)) != 0) {
 366                 ddi_soft_state_fini(&sf_state);
 367                 return (i);
 368         }
 369 
 370         mutex_init(&sf_global_mutex, NULL, MUTEX_DRIVER, NULL);
 371         sf_watch_running = 0;
 372         cv_init(&sf_watch_cv, NULL, CV_DRIVER, NULL);
 373 
 374         if ((i = mod_install(&modlinkage)) != 0) {
 375                 mutex_destroy(&sf_global_mutex);
 376                 cv_destroy(&sf_watch_cv);
 377                 scsi_hba_fini(&modlinkage);
 378                 ddi_soft_state_fini(&sf_state);
 379                 return (i);
 380         }
 381 
 382         return (i);
 383 }
 384 
 385 
 386 /*
 387  * remove this driver module from the system
 388  */
 389 int
 390 _fini(void)
 391 {
 392         int     i;
 393 
 394         if ((i = mod_remove(&modlinkage)) == 0) {
 395                 scsi_hba_fini(&modlinkage);
 396                 mutex_destroy(&sf_global_mutex);
 397                 cv_destroy(&sf_watch_cv);
 398                 ddi_soft_state_fini(&sf_state);
 399         }
 400         return (i);
 401 }
 402 
 403 
 404 int
 405 _info(struct modinfo *modinfop)
 406 {
 407         return (mod_info(&modlinkage, modinfop));
 408 }
 409 
 410 /*
 411  * Given the device number return the devinfo pointer or instance
 412  */
 413 /*ARGSUSED*/
 414 static int
 415 sf_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 416 {
 417         int             instance = SF_MINOR2INST(getminor((dev_t)arg));
 418         struct sf       *sf;
 419 
 420         switch (infocmd) {
 421         case DDI_INFO_DEVT2DEVINFO:
 422                 sf = ddi_get_soft_state(sf_state, instance);
 423                 if (sf != NULL)
 424                         *result = sf->sf_dip;
 425                 else {
 426                         *result = NULL;
 427                         return (DDI_FAILURE);
 428                 }
 429                 break;
 430 
 431         case DDI_INFO_DEVT2INSTANCE:
 432                 *result = (void *)(uintptr_t)instance;
 433                 break;
 434         default:
 435                 return (DDI_FAILURE);
 436         }
 437         return (DDI_SUCCESS);
 438 }
 439 
 440 /*
 441  * either attach or resume this driver
 442  */
 443 static int
 444 sf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 445 {
 446         int instance;
 447         int mutex_initted = FALSE;
 448         uint_t ccount;
 449         size_t i, real_size;
 450         struct fcal_transport *handle;
 451         char buf[64];
 452         struct sf *sf, *tsf;
 453         scsi_hba_tran_t *tran = NULL;
 454         int     handle_bound = FALSE;
 455         kthread_t *tp;
 456 
 457 
 458         switch ((int)cmd) {
 459 
 460         case DDI_RESUME:
 461 
 462                 /*
 463                  * we've previously been SF_STATE_OFFLINEd by a DDI_SUSPEND,
 464                  * so time to undo that and get going again by forcing a
 465                  * lip
 466                  */
 467 
 468                 instance = ddi_get_instance(dip);
 469 
 470                 sf = ddi_get_soft_state(sf_state, instance);
 471                 SF_DEBUG(2, (sf, CE_CONT,
 472                     "sf_attach: DDI_RESUME for sf%d\n", instance));
 473                 if (sf == NULL) {
 474                         cmn_err(CE_WARN, "sf%d: bad soft state", instance);
 475                         return (DDI_FAILURE);
 476                 }
 477 
 478                 /*
 479                  * clear suspended flag so that normal operations can resume
 480                  */
 481                 mutex_enter(&sf->sf_mutex);
 482                 sf->sf_state &= ~SF_STATE_SUSPENDED;
 483                 mutex_exit(&sf->sf_mutex);
 484 
 485                 /*
 486                  * force a login by setting our state to offline
 487                  */
 488                 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
 489                 sf->sf_state = SF_STATE_OFFLINE;
 490 
 491                 /*
 492                  * call transport routine to register state change and
 493                  * ELS callback routines (to register us as a ULP)
 494                  */
 495                 soc_add_ulp(sf->sf_sochandle, sf->sf_socp,
 496                     sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP,
 497                     sf_statec_callback, sf_unsol_els_callback, NULL, sf);
 498 
 499                 /*
 500                  * call transport routine to force loop initialization
 501                  */
 502                 (void) soc_force_lip(sf->sf_sochandle, sf->sf_socp,
 503                     sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP);
 504 
 505                 /*
 506                  * increment watchdog init flag, setting watchdog timeout
 507                  * if we are the first (since somebody has to do it)
 508                  */
 509                 mutex_enter(&sf_global_mutex);
 510                 if (!sf_watchdog_init++) {
 511                         mutex_exit(&sf_global_mutex);
 512                         sf_watchdog_id = timeout(sf_watch,
 513                             (caddr_t)0, sf_watchdog_tick);
 514                 } else {
 515                         mutex_exit(&sf_global_mutex);
 516                 }
 517 
 518                 return (DDI_SUCCESS);
 519 
 520         case DDI_ATTACH:
 521 
 522                 /*
 523                  * this instance attaching for the first time
 524                  */
 525 
 526                 instance = ddi_get_instance(dip);
 527 
 528                 if (ddi_soft_state_zalloc(sf_state, instance) !=
 529                     DDI_SUCCESS) {
 530                         cmn_err(CE_WARN, "sf%d: failed to allocate soft state",
 531                             instance);
 532                         return (DDI_FAILURE);
 533                 }
 534 
 535                 sf = ddi_get_soft_state(sf_state, instance);
 536                 SF_DEBUG(4, (sf, CE_CONT,
 537                     "sf_attach: DDI_ATTACH for sf%d\n", instance));
 538                 if (sf == NULL) {
 539                         /* this shouldn't happen since we just allocated it */
 540                         cmn_err(CE_WARN, "sf%d: bad soft state", instance);
 541                         return (DDI_FAILURE);
 542                 }
 543 
 544                 /*
 545                  * from this point on, if there's an error, we must de-allocate
 546                  * soft state before returning DDI_FAILURE
 547                  */
 548 
 549                 if ((handle = ddi_get_parent_data(dip)) == NULL) {
 550                         cmn_err(CE_WARN,
 551                             "sf%d: failed to obtain transport handle",
 552                             instance);
 553                         goto fail;
 554                 }
 555 
 556                 /* fill in our soft state structure */
 557                 sf->sf_dip = dip;
 558                 sf->sf_state = SF_STATE_INIT;
 559                 sf->sf_throttle = handle->fcal_cmdmax;
 560                 sf->sf_sochandle = handle;
 561                 sf->sf_socp = handle->fcal_handle;
 562                 sf->sf_check_n_close = 0;
 563 
 564                 /* create a command/response buffer pool for this instance */
 565                 if (sf_add_cr_pool(sf) != DDI_SUCCESS) {
 566                         cmn_err(CE_WARN,
 567                             "sf%d: failed to allocate command/response pool",
 568                             instance);
 569                         goto fail;
 570                 }
 571 
 572                 /* create a a cache for this instance */
 573                 (void) sprintf(buf, "sf%d_cache", instance);
 574                 sf->sf_pkt_cache = kmem_cache_create(buf,
 575                     sizeof (fcal_packet_t) + sizeof (struct sf_pkt) +
 576                     scsi_pkt_size(), 8,
 577                     sf_kmem_cache_constructor, sf_kmem_cache_destructor,
 578                     NULL, NULL, NULL, 0);
 579                 if (sf->sf_pkt_cache == NULL) {
 580                         cmn_err(CE_WARN, "sf%d: failed to allocate kmem cache",
 581                             instance);
 582                         goto fail;
 583                 }
 584 
 585                 /* set up a handle and allocate memory for DMA */
 586                 if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->
 587                     fcal_dmaattr, DDI_DMA_DONTWAIT, NULL, &sf->
 588                     sf_lilp_dmahandle) != DDI_SUCCESS) {
 589                         cmn_err(CE_WARN,
 590                             "sf%d: failed to allocate dma handle for lilp map",
 591                             instance);
 592                         goto fail;
 593                 }
 594                 i = sizeof (struct fcal_lilp_map) + 1;
 595                 if (ddi_dma_mem_alloc(sf->sf_lilp_dmahandle,
 596                     i, sf->sf_sochandle->
 597                     fcal_accattr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
 598                     (caddr_t *)&sf->sf_lilp_map, &real_size,
 599                     &sf->sf_lilp_acchandle) != DDI_SUCCESS) {
 600                         cmn_err(CE_WARN, "sf%d: failed to allocate lilp map",
 601                             instance);
 602                         goto fail;
 603                 }
 604                 if (real_size < i) {
 605                         /* no error message ??? */
 606                         goto fail;              /* trouble allocating memory */
 607                 }
 608 
 609                 /*
 610                  * set up the address for the DMA transfers (getting a cookie)
 611                  */
 612                 if (ddi_dma_addr_bind_handle(sf->sf_lilp_dmahandle, NULL,
 613                     (caddr_t)sf->sf_lilp_map, real_size,
 614                     DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
 615                     &sf->sf_lilp_dmacookie, &ccount) != DDI_DMA_MAPPED) {
 616                         cmn_err(CE_WARN,
 617                             "sf%d: failed to bind dma handle for lilp map",
 618                             instance);
 619                         goto fail;
 620                 }
 621                 handle_bound = TRUE;
 622                 /* ensure only one cookie was allocated */
 623                 if (ccount != 1) {
 624                         goto fail;
 625                 }
 626 
 627                 /* ensure LILP map and DMA cookie addresses are even?? */
 628                 sf->sf_lilp_map = (struct fcal_lilp_map *)(((uintptr_t)sf->
 629                     sf_lilp_map + 1) & ~1);
 630                 sf->sf_lilp_dmacookie.dmac_address = (sf->
 631                     sf_lilp_dmacookie.dmac_address + 1) & ~1;
 632 
 633                 /* set up all of our mutexes and condition variables */
 634                 mutex_init(&sf->sf_mutex, NULL, MUTEX_DRIVER, NULL);
 635                 mutex_init(&sf->sf_cmd_mutex, NULL, MUTEX_DRIVER, NULL);
 636                 mutex_init(&sf->sf_cr_mutex, NULL, MUTEX_DRIVER, NULL);
 637                 mutex_init(&sf->sf_hp_daemon_mutex, NULL, MUTEX_DRIVER, NULL);
 638                 cv_init(&sf->sf_cr_cv, NULL, CV_DRIVER, NULL);
 639                 cv_init(&sf->sf_hp_daemon_cv, NULL, CV_DRIVER, NULL);
 640 
 641                 mutex_initted = TRUE;
 642 
 643                 /* create our devctl minor node */
 644                 if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
 645                     SF_INST2DEVCTL_MINOR(instance),
 646                     DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
 647                         cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed"
 648                             " for devctl", instance);
 649                         goto fail;
 650                 }
 651 
 652                 /* create fc minor node */
 653                 if (ddi_create_minor_node(dip, "fc", S_IFCHR,
 654                     SF_INST2FC_MINOR(instance), DDI_NT_FC_ATTACHMENT_POINT,
 655                     0) != DDI_SUCCESS) {
 656                         cmn_err(CE_WARN, "sf%d: ddi_create_minor_node failed"
 657                             " for fc", instance);
 658                         goto fail;
 659                 }
 660                 /* allocate a SCSI transport structure */
 661                 tran = scsi_hba_tran_alloc(dip, 0);
 662                 if (tran == NULL) {
 663                         /* remove all minor nodes created */
 664                         ddi_remove_minor_node(dip, NULL);
 665                         cmn_err(CE_WARN, "sf%d: scsi_hba_tran_alloc failed",
 666                             instance);
 667                         goto fail;
 668                 }
 669 
 670                 /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
 671                 scsi_size_clean(dip);           /* SCSI_SIZE_CLEAN_VERIFY ok */
 672 
 673                 /* save ptr to new transport structure and fill it in */
 674                 sf->sf_tran = tran;
 675 
 676                 tran->tran_hba_private               = sf;
 677                 tran->tran_tgt_private               = NULL;
 678                 tran->tran_tgt_init          = sf_scsi_tgt_init;
 679                 tran->tran_tgt_probe         = NULL;
 680                 tran->tran_tgt_free          = sf_scsi_tgt_free;
 681 
 682                 tran->tran_start             = sf_start;
 683                 tran->tran_abort             = sf_abort;
 684                 tran->tran_reset             = sf_reset;
 685                 tran->tran_getcap            = sf_getcap;
 686                 tran->tran_setcap            = sf_setcap;
 687                 tran->tran_init_pkt          = sf_scsi_init_pkt;
 688                 tran->tran_destroy_pkt               = sf_scsi_destroy_pkt;
 689                 tran->tran_dmafree           = sf_scsi_dmafree;
 690                 tran->tran_sync_pkt          = sf_scsi_sync_pkt;
 691                 tran->tran_reset_notify              = sf_scsi_reset_notify;
 692 
 693                 /*
 694                  * register event notification routines with scsa
 695                  */
 696                 tran->tran_get_eventcookie   = sf_bus_get_eventcookie;
 697                 tran->tran_add_eventcall     = sf_bus_add_eventcall;
 698                 tran->tran_remove_eventcall  = sf_bus_remove_eventcall;
 699                 tran->tran_post_event                = sf_bus_post_event;
 700 
 701                 /*
 702                  * register bus configure/unconfigure
 703                  */
 704                 tran->tran_bus_config                = sf_scsi_bus_config;
 705                 tran->tran_bus_unconfig              = sf_scsi_bus_unconfig;
 706 
 707                 /*
 708                  * allocate an ndi event handle
 709                  */
 710                 sf->sf_event_defs = (ndi_event_definition_t *)
 711                     kmem_zalloc(sizeof (sf_event_defs), KM_SLEEP);
 712 
 713                 bcopy(sf_event_defs, sf->sf_event_defs,
 714                     sizeof (sf_event_defs));
 715 
 716                 (void) ndi_event_alloc_hdl(dip, NULL,
 717                     &sf->sf_event_hdl, NDI_SLEEP);
 718 
 719                 sf->sf_events.ndi_events_version = NDI_EVENTS_REV1;
 720                 sf->sf_events.ndi_n_events = SF_N_NDI_EVENTS;
 721                 sf->sf_events.ndi_event_defs = sf->sf_event_defs;
 722 
 723                 if (ndi_event_bind_set(sf->sf_event_hdl,
 724                     &sf->sf_events, NDI_SLEEP) != NDI_SUCCESS) {
 725                         goto fail;
 726                 }
 727 
 728                 tran->tran_get_name          = sf_scsi_get_name;
 729                 tran->tran_get_bus_addr              = sf_scsi_get_bus_addr;
 730 
 731                 /* setup and attach SCSI hba transport */
 732                 if (scsi_hba_attach_setup(dip, sf->sf_sochandle->
 733                     fcal_dmaattr, tran, SCSI_HBA_TRAN_CLONE) != DDI_SUCCESS) {
 734                         cmn_err(CE_WARN, "sf%d: scsi_hba_attach_setup failed",
 735                             instance);
 736                         goto fail;
 737                 }
 738 
 739                 /* set up kstats */
 740                 if ((sf->sf_ksp = kstat_create("sf", instance, "statistics",
 741                     "controller", KSTAT_TYPE_RAW, sizeof (struct sf_stats),
 742                     KSTAT_FLAG_VIRTUAL)) == NULL) {
 743                         cmn_err(CE_WARN, "sf%d: failed to create kstat",
 744                             instance);
 745                 } else {
 746                         sf->sf_stats.version = 2;
 747                         (void) sprintf(sf->sf_stats.drvr_name,
 748                         "%s: %s", SF_NAME, sf_version);
 749                         sf->sf_ksp->ks_data = (void *)&sf->sf_stats;
 750                         sf->sf_ksp->ks_private = sf;
 751                         sf->sf_ksp->ks_update = sf_kstat_update;
 752                         kstat_install(sf->sf_ksp);
 753                 }
 754 
 755                 /* create the hotplug thread */
 756                 mutex_enter(&sf->sf_hp_daemon_mutex);
 757                 tp = thread_create(NULL, 0,
 758                     (void (*)())sf_hp_daemon, sf, 0, &p0, TS_RUN, minclsyspri);
 759                 sf->sf_hp_tid = tp->t_did;
 760                 mutex_exit(&sf->sf_hp_daemon_mutex);
 761 
 762                 /* add this soft state instance to the head of the list */
 763                 mutex_enter(&sf_global_mutex);
 764                 sf->sf_next = sf_head;
 765                 tsf = sf_head;
 766                 sf_head = sf;
 767 
 768                 /*
 769                  * find entry in list that has the same FC-AL handle (if any)
 770                  */
 771                 while (tsf != NULL) {
 772                         if (tsf->sf_socp == sf->sf_socp) {
 773                                 break;          /* found matching entry */
 774                         }
 775                         tsf = tsf->sf_next;
 776                 }
 777 
 778                 if (tsf != NULL) {
 779                         /* if we found a matching entry keep track of it */
 780                         sf->sf_sibling = tsf;
 781                 }
 782 
 783                 /*
 784                  * increment watchdog init flag, setting watchdog timeout
 785                  * if we are the first (since somebody has to do it)
 786                  */
 787                 if (!sf_watchdog_init++) {
 788                         mutex_exit(&sf_global_mutex);
 789                         sf_watchdog_tick = sf_watchdog_timeout *
 790                             drv_usectohz(1000000);
 791                         sf_watchdog_id = timeout(sf_watch,
 792                             NULL, sf_watchdog_tick);
 793                 } else {
 794                         mutex_exit(&sf_global_mutex);
 795                 }
 796 
 797                 if (tsf != NULL) {
 798                         /*
 799                          * set up matching entry to be our sibling
 800                          */
 801                         mutex_enter(&tsf->sf_mutex);
 802                         tsf->sf_sibling = sf;
 803                         mutex_exit(&tsf->sf_mutex);
 804                 }
 805 
 806                 /*
 807                  * create this property so that PM code knows we want
 808                  * to be suspended at PM time
 809                  */
 810                 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 811                     PM_HARDWARE_STATE_PROP, PM_NEEDS_SUSPEND_RESUME);
 812 
 813                 /* log the fact that we have a new device */
 814                 ddi_report_dev(dip);
 815 
 816                 /*
 817                  * force a login by setting our state to offline
 818                  */
 819                 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
 820                 sf->sf_state = SF_STATE_OFFLINE;
 821 
 822                 /*
 823                  * call transport routine to register state change and
 824                  * ELS callback routines (to register us as a ULP)
 825                  */
 826                 soc_add_ulp(sf->sf_sochandle, sf->sf_socp,
 827                     sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP,
 828                     sf_statec_callback, sf_unsol_els_callback, NULL, sf);
 829 
 830                 /*
 831                  * call transport routine to force loop initialization
 832                  */
 833                 (void) soc_force_lip(sf->sf_sochandle, sf->sf_socp,
 834                     sf->sf_sochandle->fcal_portno, 0, FCAL_NO_LIP);
 835                 sf->sf_reset_time = ddi_get_lbolt64();
 836                 return (DDI_SUCCESS);
 837 
 838         default:
 839                 return (DDI_FAILURE);
 840         }
 841 
 842 fail:
 843         cmn_err(CE_WARN, "sf%d: failed to attach", instance);
 844 
 845         /*
 846          * Unbind and free event set
 847          */
 848         if (sf->sf_event_hdl) {
 849                 (void) ndi_event_unbind_set(sf->sf_event_hdl,
 850                     &sf->sf_events, NDI_SLEEP);
 851                 (void) ndi_event_free_hdl(sf->sf_event_hdl);
 852         }
 853 
 854         if (sf->sf_event_defs) {
 855                 kmem_free(sf->sf_event_defs, sizeof (sf_event_defs));
 856         }
 857 
 858         if (sf->sf_tran != NULL) {
 859                 scsi_hba_tran_free(sf->sf_tran);
 860         }
 861         while (sf->sf_cr_pool != NULL) {
 862                 sf_crpool_free(sf);
 863         }
 864         if (sf->sf_lilp_dmahandle != NULL) {
 865                 if (handle_bound) {
 866                         (void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle);
 867                 }
 868                 ddi_dma_free_handle(&sf->sf_lilp_dmahandle);
 869         }
 870         if (sf->sf_pkt_cache != NULL) {
 871                 kmem_cache_destroy(sf->sf_pkt_cache);
 872         }
 873         if (sf->sf_lilp_map != NULL) {
 874                 ddi_dma_mem_free(&sf->sf_lilp_acchandle);
 875         }
 876         if (sf->sf_ksp != NULL) {
 877                 kstat_delete(sf->sf_ksp);
 878         }
 879         if (mutex_initted) {
 880                 mutex_destroy(&sf->sf_mutex);
 881                 mutex_destroy(&sf->sf_cmd_mutex);
 882                 mutex_destroy(&sf->sf_cr_mutex);
 883                 mutex_destroy(&sf->sf_hp_daemon_mutex);
 884                 cv_destroy(&sf->sf_cr_cv);
 885                 cv_destroy(&sf->sf_hp_daemon_cv);
 886         }
 887         mutex_enter(&sf_global_mutex);
 888 
 889         /*
 890          * kill off the watchdog if we are the last instance
 891          */
 892         if (!--sf_watchdog_init) {
 893                 timeout_id_t tid = sf_watchdog_id;
 894                 mutex_exit(&sf_global_mutex);
 895                 (void) untimeout(tid);
 896         } else {
 897                 mutex_exit(&sf_global_mutex);
 898         }
 899 
 900         ddi_soft_state_free(sf_state, instance);
 901 
 902         if (tran != NULL) {
 903                 /* remove all minor nodes */
 904                 ddi_remove_minor_node(dip, NULL);
 905         }
 906 
 907         return (DDI_FAILURE);
 908 }
 909 
 910 
 911 /* ARGSUSED */
 912 static int
 913 sf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 914 {
 915         struct sf               *sf;
 916         int                     instance;
 917         int                     i;
 918         struct sf_target        *target;
 919         timeout_id_t            tid;
 920 
 921 
 922 
 923         /* NO OTHER THREADS ARE RUNNING */
 924 
 925         instance = ddi_get_instance(dip);
 926 
 927         if ((sf = ddi_get_soft_state(sf_state, instance)) == NULL) {
 928                 cmn_err(CE_WARN, "sf_detach, sf%d: bad soft state", instance);
 929                 return (DDI_FAILURE);
 930         }
 931 
 932         switch (cmd) {
 933 
 934         case DDI_SUSPEND:
 935                 /*
 936                  * suspend our instance
 937                  */
 938 
 939                 SF_DEBUG(2, (sf, CE_CONT,
 940                     "sf_detach: DDI_SUSPEND for sf%d\n", instance));
 941                 /*
 942                  * There is a race condition in socal where while doing
 943                  * callbacks if a ULP removes it self from the callback list
 944                  * the for loop in socal may panic as cblist is junk and
 945                  * while trying to get cblist->next the system will panic.
 946                  */
 947 
 948                 /* call transport to remove our unregister our callbacks */
 949                 soc_remove_ulp(sf->sf_sochandle, sf->sf_socp,
 950                     sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf);
 951 
 952                 /*
 953                  * begin process of clearing outstanding commands
 954                  * by issuing a lip
 955                  */
 956                 sf_force_lip(sf);
 957 
 958                 /*
 959                  * toggle the device OFFLINE in order to cause
 960                  * outstanding commands to drain
 961                  */
 962                 mutex_enter(&sf->sf_mutex);
 963                 sf->sf_lip_cnt++;
 964                 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
 965                 sf->sf_state = (SF_STATE_OFFLINE | SF_STATE_SUSPENDED);
 966                 for (i = 0; i < sf_max_targets; i++) {
 967                         target = sf->sf_targets[i];
 968                         if (target != NULL) {
 969                                 struct sf_target *ntarget;
 970 
 971                                 mutex_enter(&target->sft_mutex);
 972                                 if (!(target->sft_state & SF_TARGET_OFFLINE)) {
 973                                         target->sft_state |=
 974                                             (SF_TARGET_BUSY | SF_TARGET_MARK);
 975                                 }
 976                                 /* do this for all LUNs as well */
 977                                 for (ntarget = target->sft_next_lun;
 978                                     ntarget;
 979                                     ntarget = ntarget->sft_next_lun) {
 980                                         mutex_enter(&ntarget->sft_mutex);
 981                                         if (!(ntarget->sft_state &
 982                                             SF_TARGET_OFFLINE)) {
 983                                                 ntarget->sft_state |=
 984                                                     (SF_TARGET_BUSY |
 985                                                     SF_TARGET_MARK);
 986                                         }
 987                                         mutex_exit(&ntarget->sft_mutex);
 988                                 }
 989                                 mutex_exit(&target->sft_mutex);
 990                         }
 991                 }
 992                 mutex_exit(&sf->sf_mutex);
 993                 mutex_enter(&sf_global_mutex);
 994 
 995                 /*
 996                  * kill off the watchdog if we are the last instance
 997                  */
 998                 if (!--sf_watchdog_init) {
 999                         tid = sf_watchdog_id;
1000                         mutex_exit(&sf_global_mutex);
1001                         (void) untimeout(tid);
1002                 } else {
1003                         mutex_exit(&sf_global_mutex);
1004                 }
1005 
1006                 return (DDI_SUCCESS);
1007 
1008         case DDI_DETACH:
1009                 /*
1010                  * detach this instance
1011                  */
1012 
1013                 SF_DEBUG(2, (sf, CE_CONT,
1014                     "sf_detach: DDI_DETACH for sf%d\n", instance));
1015 
1016                 /* remove this "sf" from the list of sf softstates */
1017                 sf_softstate_unlink(sf);
1018 
1019                 /*
1020                  * prior to taking any DDI_DETACH actions, toggle the
1021                  * device OFFLINE in order to cause outstanding
1022                  * commands to drain
1023                  */
1024                 mutex_enter(&sf->sf_mutex);
1025                 sf->sf_lip_cnt++;
1026                 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
1027                 sf->sf_state = SF_STATE_OFFLINE;
1028                 for (i = 0; i < sf_max_targets; i++) {
1029                         target = sf->sf_targets[i];
1030                         if (target != NULL) {
1031                                 struct sf_target *ntarget;
1032 
1033                                 mutex_enter(&target->sft_mutex);
1034                                 if (!(target->sft_state & SF_TARGET_OFFLINE)) {
1035                                         target->sft_state |=
1036                                             (SF_TARGET_BUSY | SF_TARGET_MARK);
1037                                 }
1038                                 for (ntarget = target->sft_next_lun;
1039                                     ntarget;
1040                                     ntarget = ntarget->sft_next_lun) {
1041                                         mutex_enter(&ntarget->sft_mutex);
1042                                         if (!(ntarget->sft_state &
1043                                             SF_TARGET_OFFLINE)) {
1044                                                 ntarget->sft_state |=
1045                                                     (SF_TARGET_BUSY |
1046                                                     SF_TARGET_MARK);
1047                                         }
1048                                         mutex_exit(&ntarget->sft_mutex);
1049                                 }
1050                                 mutex_exit(&target->sft_mutex);
1051                         }
1052                 }
1053                 mutex_exit(&sf->sf_mutex);
1054 
1055                 /* call transport to remove and unregister our callbacks */
1056                 soc_remove_ulp(sf->sf_sochandle, sf->sf_socp,
1057                     sf->sf_sochandle->fcal_portno, TYPE_SCSI_FCP, sf);
1058 
1059                 /*
1060                  * kill off the watchdog if we are the last instance
1061                  */
1062                 mutex_enter(&sf_global_mutex);
1063                 if (!--sf_watchdog_init) {
1064                         tid = sf_watchdog_id;
1065                         mutex_exit(&sf_global_mutex);
1066                         (void) untimeout(tid);
1067                 } else {
1068                         mutex_exit(&sf_global_mutex);
1069                 }
1070 
1071                 /* signal sf_hp_daemon() to exit and wait for exit */
1072                 mutex_enter(&sf->sf_hp_daemon_mutex);
1073                 ASSERT(sf->sf_hp_tid);
1074                 sf->sf_hp_exit = 1;          /* flag exit */
1075                 cv_signal(&sf->sf_hp_daemon_cv);
1076                 mutex_exit(&sf->sf_hp_daemon_mutex);
1077                 thread_join(sf->sf_hp_tid);  /* wait for hotplug to exit */
1078 
1079                 /*
1080                  * Unbind and free event set
1081                  */
1082                 if (sf->sf_event_hdl) {
1083                         (void) ndi_event_unbind_set(sf->sf_event_hdl,
1084                             &sf->sf_events, NDI_SLEEP);
1085                         (void) ndi_event_free_hdl(sf->sf_event_hdl);
1086                 }
1087 
1088                 if (sf->sf_event_defs) {
1089                         kmem_free(sf->sf_event_defs, sizeof (sf_event_defs));
1090                 }
1091 
1092                 /* detach this instance of the HBA driver */
1093                 (void) scsi_hba_detach(dip);
1094                 scsi_hba_tran_free(sf->sf_tran);
1095 
1096                 /* deallocate/unbind DMA handle for lilp map */
1097                 if (sf->sf_lilp_map != NULL) {
1098                         (void) ddi_dma_unbind_handle(sf->sf_lilp_dmahandle);
1099                         if (sf->sf_lilp_dmahandle != NULL) {
1100                                 ddi_dma_free_handle(&sf->sf_lilp_dmahandle);
1101                         }
1102                         ddi_dma_mem_free(&sf->sf_lilp_acchandle);
1103                 }
1104 
1105                 /*
1106                  * the kmem cache must be destroyed before free'ing
1107                  * up the crpools
1108                  *
1109                  * our finagle of "ntot" and "nfree"
1110                  * causes an ASSERT failure in "sf_cr_free()"
1111                  * if the kmem cache is free'd after invoking
1112                  * "sf_crpool_free()".
1113                  */
1114                 kmem_cache_destroy(sf->sf_pkt_cache);
1115 
1116                 SF_DEBUG(2, (sf, CE_CONT,
1117                     "sf_detach: sf_crpool_free() for instance 0x%x\n",
1118                     instance));
1119                 while (sf->sf_cr_pool != NULL) {
1120                         /*
1121                          * set ntot to nfree for this particular entry
1122                          *
1123                          * this causes sf_crpool_free() to update
1124                          * the cr_pool list when deallocating this entry
1125                          */
1126                         sf->sf_cr_pool->ntot = sf->sf_cr_pool->nfree;
1127                         sf_crpool_free(sf);
1128                 }
1129 
1130                 /*
1131                  * now that the cr_pool's are gone it's safe
1132                  * to destroy all softstate mutex's and cv's
1133                  */
1134                 mutex_destroy(&sf->sf_mutex);
1135                 mutex_destroy(&sf->sf_cmd_mutex);
1136                 mutex_destroy(&sf->sf_cr_mutex);
1137                 mutex_destroy(&sf->sf_hp_daemon_mutex);
1138                 cv_destroy(&sf->sf_cr_cv);
1139                 cv_destroy(&sf->sf_hp_daemon_cv);
1140 
1141                 /* remove all minor nodes from the device tree */
1142                 ddi_remove_minor_node(dip, NULL);
1143 
1144                 /* remove properties created during attach() */
1145                 ddi_prop_remove_all(dip);
1146 
1147                 /* remove kstat's if present */
1148                 if (sf->sf_ksp != NULL) {
1149                         kstat_delete(sf->sf_ksp);
1150                 }
1151 
1152                 SF_DEBUG(2, (sf, CE_CONT,
1153                     "sf_detach: ddi_soft_state_free() for instance 0x%x\n",
1154                     instance));
1155                 ddi_soft_state_free(sf_state, instance);
1156                 return (DDI_SUCCESS);
1157 
1158         default:
1159                 SF_DEBUG(2, (sf, CE_CONT, "sf_detach: sf%d unknown cmd %x\n",
1160                     instance, (int)cmd));
1161                 return (DDI_FAILURE);
1162         }
1163 }
1164 
1165 
1166 /*
1167  * sf_softstate_unlink() - remove an sf instance from the list of softstates
1168  */
1169 static void
1170 sf_softstate_unlink(struct sf *sf)
1171 {
1172         struct sf       *sf_ptr;
1173         struct sf       *sf_found_sibling;
1174         struct sf       *sf_reposition = NULL;
1175 
1176 
1177         mutex_enter(&sf_global_mutex);
1178         while (sf_watch_running) {
1179                 /* Busy working the list -- wait */
1180                 cv_wait(&sf_watch_cv, &sf_global_mutex);
1181         }
1182         if ((sf_found_sibling = sf->sf_sibling) != NULL) {
1183                 /*
1184                  * we have a sibling so NULL out its reference to us
1185                  */
1186                 mutex_enter(&sf_found_sibling->sf_mutex);
1187                 sf_found_sibling->sf_sibling = NULL;
1188                 mutex_exit(&sf_found_sibling->sf_mutex);
1189         }
1190 
1191         /* remove our instance from the global list */
1192         if (sf == sf_head) {
1193                 /* we were at at head of the list */
1194                 sf_head = sf->sf_next;
1195         } else {
1196                 /* find us in the list */
1197                 for (sf_ptr = sf_head;
1198                     sf_ptr != NULL;
1199                     sf_ptr = sf_ptr->sf_next) {
1200                         if (sf_ptr == sf) {
1201                                 break;
1202                         }
1203                         /* remember this place */
1204                         sf_reposition = sf_ptr;
1205                 }
1206                 ASSERT(sf_ptr == sf);
1207                 ASSERT(sf_reposition != NULL);
1208 
1209                 sf_reposition->sf_next = sf_ptr->sf_next;
1210         }
1211         mutex_exit(&sf_global_mutex);
1212 }
1213 
1214 
1215 static int
1216 sf_scsi_bus_config(dev_info_t *parent, uint_t flag,
1217     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
1218 {
1219         int64_t         reset_delay;
1220         struct sf       *sf;
1221 
1222         sf = ddi_get_soft_state(sf_state, ddi_get_instance(parent));
1223         ASSERT(sf);
1224 
1225         reset_delay = (int64_t)(USEC_TO_TICK(SF_INIT_WAIT_TIMEOUT)) -
1226             (ddi_get_lbolt64() - sf->sf_reset_time);
1227         if (reset_delay < 0)
1228                 reset_delay = 0;
1229 
1230         if (sf_bus_config_debug)
1231                 flag |= NDI_DEVI_DEBUG;
1232 
1233         return (ndi_busop_bus_config(parent, flag, op,
1234             arg, childp, (clock_t)reset_delay));
1235 }
1236 
1237 static int
1238 sf_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
1239     ddi_bus_config_op_t op, void *arg)
1240 {
1241         if (sf_bus_config_debug)
1242                 flag |= NDI_DEVI_DEBUG;
1243 
1244         return (ndi_busop_bus_unconfig(parent, flag, op, arg));
1245 }
1246 
1247 
1248 /*
1249  * called by transport to initialize a SCSI target
1250  */
1251 /* ARGSUSED */
1252 static int
1253 sf_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1254     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
1255 {
1256 #ifdef RAID_LUNS
1257         int lun;
1258 #else
1259         int64_t lun;
1260 #endif
1261         struct sf_target *target;
1262         struct sf *sf = (struct sf *)hba_tran->tran_hba_private;
1263         int i, t_len;
1264         unsigned int lip_cnt;
1265         unsigned char wwn[FC_WWN_SIZE];
1266 
1267 
1268         /* get and validate our SCSI target ID */
1269         i = sd->sd_address.a_target;
1270         if (i >= sf_max_targets) {
1271                 return (DDI_NOT_WELL_FORMED);
1272         }
1273 
1274         /* get our port WWN property */
1275         t_len = sizeof (wwn);
1276         if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1277             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP,
1278             (caddr_t)&wwn, &t_len) != DDI_SUCCESS) {
1279                 /* no port WWN property - ignore the OBP stub node */
1280                 return (DDI_NOT_WELL_FORMED);
1281         }
1282 
1283         /* get our LIP count property */
1284         t_len = sizeof (lip_cnt);
1285         if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1286             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, LIP_CNT_PROP,
1287             (caddr_t)&lip_cnt, &t_len) != DDI_SUCCESS) {
1288                 return (DDI_FAILURE);
1289         }
1290         /* and our LUN property */
1291         t_len = sizeof (lun);
1292         if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1293             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun",
1294             (caddr_t)&lun, &t_len) != DDI_SUCCESS) {
1295                 return (DDI_FAILURE);
1296         }
1297 
1298         /* find the target structure for this instance */
1299         mutex_enter(&sf->sf_mutex);
1300         if ((target = sf_lookup_target(sf, wwn, lun)) == NULL) {
1301                 mutex_exit(&sf->sf_mutex);
1302                 return (DDI_FAILURE);
1303         }
1304 
1305         mutex_enter(&target->sft_mutex);
1306         if ((sf->sf_lip_cnt == lip_cnt) && !(target->sft_state
1307             & SF_TARGET_INIT_DONE)) {
1308                 /*
1309                  * set links between HBA transport and target structures
1310                  * and set done flag
1311                  */
1312                 hba_tran->tran_tgt_private = target;
1313                 target->sft_tran = hba_tran;
1314                 target->sft_state |= SF_TARGET_INIT_DONE;
1315         } else {
1316                 /* already initialized ?? */
1317                 mutex_exit(&target->sft_mutex);
1318                 mutex_exit(&sf->sf_mutex);
1319                 return (DDI_FAILURE);
1320         }
1321         mutex_exit(&target->sft_mutex);
1322         mutex_exit(&sf->sf_mutex);
1323 
1324         return (DDI_SUCCESS);
1325 }
1326 
1327 
1328 /*
1329  * called by transport to free a target
1330  */
1331 /* ARGSUSED */
1332 static void
1333 sf_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
1334     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
1335 {
1336         struct sf_target *target = hba_tran->tran_tgt_private;
1337 
1338         if (target != NULL) {
1339                 mutex_enter(&target->sft_mutex);
1340                 target->sft_tran = NULL;
1341                 target->sft_state &= ~SF_TARGET_INIT_DONE;
1342                 mutex_exit(&target->sft_mutex);
1343         }
1344 }
1345 
1346 
1347 /*
1348  * allocator for non-std size cdb/pkt_private/status -- return TRUE iff
1349  * success, else return FALSE
1350  */
1351 /*ARGSUSED*/
1352 static int
1353 sf_pkt_alloc_extern(struct sf *sf, struct sf_pkt *cmd,
1354     int tgtlen, int statuslen, int kf)
1355 {
1356         caddr_t scbp, tgt;
1357         int failure = FALSE;
1358         struct scsi_pkt *pkt = CMD2PKT(cmd);
1359 
1360 
1361         tgt = scbp = NULL;
1362 
1363         if (tgtlen > PKT_PRIV_LEN) {
1364                 if ((tgt = kmem_zalloc(tgtlen, kf)) == NULL) {
1365                         failure = TRUE;
1366                 } else {
1367                         cmd->cmd_flags |= CFLAG_PRIVEXTERN;
1368                         pkt->pkt_private = tgt;
1369                 }
1370         }
1371         if (statuslen > EXTCMDS_STATUS_SIZE) {
1372                 if ((scbp = kmem_zalloc((size_t)statuslen, kf)) == NULL) {
1373                         failure = TRUE;
1374                 } else {
1375                         cmd->cmd_flags |= CFLAG_SCBEXTERN;
1376                         pkt->pkt_scbp = (opaque_t)scbp;
1377                 }
1378         }
1379         if (failure) {
1380                 sf_pkt_destroy_extern(sf, cmd);
1381         }
1382         return (failure);
1383 }
1384 
1385 
1386 /*
1387  * deallocator for non-std size cdb/pkt_private/status
1388  */
1389 static void
1390 sf_pkt_destroy_extern(struct sf *sf, struct sf_pkt *cmd)
1391 {
1392         struct scsi_pkt *pkt = CMD2PKT(cmd);
1393 
1394         if (cmd->cmd_flags & CFLAG_FREE) {
1395                 cmn_err(CE_PANIC,
1396                     "sf_scsi_impl_pktfree: freeing free packet");
1397                 _NOTE(NOT_REACHED)
1398                 /* NOTREACHED */
1399         }
1400         if (cmd->cmd_flags & CFLAG_SCBEXTERN) {
1401                 kmem_free((caddr_t)pkt->pkt_scbp,
1402                     (size_t)cmd->cmd_scblen);
1403         }
1404         if (cmd->cmd_flags & CFLAG_PRIVEXTERN) {
1405                 kmem_free((caddr_t)pkt->pkt_private,
1406                     (size_t)cmd->cmd_privlen);
1407         }
1408 
1409         cmd->cmd_flags = CFLAG_FREE;
1410         kmem_cache_free(sf->sf_pkt_cache, (void *)cmd);
1411 }
1412 
1413 
1414 /*
1415  * create or initialize a SCSI packet -- called internally and
1416  * by the transport
1417  */
1418 static struct scsi_pkt *
1419 sf_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
1420     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
1421     int flags, int (*callback)(), caddr_t arg)
1422 {
1423         int kf;
1424         int failure = FALSE;
1425         struct sf_pkt *cmd;
1426         struct sf *sf = ADDR2SF(ap);
1427         struct sf_target *target = ADDR2TARGET(ap);
1428         struct sf_pkt   *new_cmd = NULL;
1429         struct fcal_packet      *fpkt;
1430         fc_frame_header_t       *hp;
1431         struct fcp_cmd *fcmd;
1432 
1433 
1434         /*
1435          * If we've already allocated a pkt once,
1436          * this request is for dma allocation only.
1437          */
1438         if (pkt == NULL) {
1439 
1440                 /*
1441                  * First step of sf_scsi_init_pkt:  pkt allocation
1442                  */
1443                 if (cmdlen > FCP_CDB_SIZE) {
1444                         return (NULL);
1445                 }
1446 
1447                 kf = (callback == SLEEP_FUNC)? KM_SLEEP: KM_NOSLEEP;
1448 
1449                 if ((cmd = kmem_cache_alloc(sf->sf_pkt_cache, kf)) != NULL) {
1450                         /*
1451                          * Selective zeroing of the pkt.
1452                          */
1453 
1454                         cmd->cmd_flags = 0;
1455                         cmd->cmd_forw = 0;
1456                         cmd->cmd_back = 0;
1457                         cmd->cmd_next = 0;
1458                         cmd->cmd_pkt = (struct scsi_pkt *)((char *)cmd +
1459                             sizeof (struct sf_pkt) + sizeof (struct
1460                             fcal_packet));
1461                         cmd->cmd_fp_pkt = (struct fcal_packet *)((char *)cmd +
1462                             sizeof (struct sf_pkt));
1463                         cmd->cmd_fp_pkt->fcal_pkt_private = (opaque_t)cmd;
1464                         cmd->cmd_state = SF_STATE_IDLE;
1465                         cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
1466                         cmd->cmd_pkt->pkt_scbp = (opaque_t)cmd->cmd_scsi_scb;
1467                         cmd->cmd_pkt->pkt_comp    = NULL;
1468                         cmd->cmd_pkt->pkt_flags   = 0;
1469                         cmd->cmd_pkt->pkt_time    = 0;
1470                         cmd->cmd_pkt->pkt_resid   = 0;
1471                         cmd->cmd_pkt->pkt_reason = 0;
1472                         cmd->cmd_cdblen = (uchar_t)cmdlen;
1473                         cmd->cmd_scblen              = statuslen;
1474                         cmd->cmd_privlen     = tgtlen;
1475                         cmd->cmd_pkt->pkt_address = *ap;
1476 
1477                         /* zero pkt_private */
1478                         (int *)(cmd->cmd_pkt->pkt_private =
1479                             cmd->cmd_pkt_private);
1480                         bzero((caddr_t)cmd->cmd_pkt->pkt_private,
1481                             PKT_PRIV_LEN);
1482                 } else {
1483                         failure = TRUE;
1484                 }
1485 
1486                 if (failure ||
1487                     (tgtlen > PKT_PRIV_LEN) ||
1488                     (statuslen > EXTCMDS_STATUS_SIZE)) {
1489                         if (!failure) {
1490                                 /* need to allocate more space */
1491                                 failure = sf_pkt_alloc_extern(sf, cmd,
1492                                     tgtlen, statuslen, kf);
1493                         }
1494                         if (failure) {
1495                                 return (NULL);
1496                         }
1497                 }
1498 
1499                 fpkt = cmd->cmd_fp_pkt;
1500                 if (cmd->cmd_block == NULL) {
1501 
1502                         /* allocate cmd/response pool buffers */
1503                         if (sf_cr_alloc(sf, cmd, callback) == DDI_FAILURE) {
1504                                 sf_pkt_destroy_extern(sf, cmd);
1505                                 return (NULL);
1506                         }
1507 
1508                         /* fill in the FC-AL packet */
1509                         fpkt->fcal_pkt_cookie = sf->sf_socp;
1510                         fpkt->fcal_pkt_comp = sf_cmd_callback;
1511                         fpkt->fcal_pkt_flags = 0;
1512                         fpkt->fcal_magic = FCALP_MAGIC;
1513                         fpkt->fcal_socal_request.sr_soc_hdr.sh_flags =
1514                             (ushort_t)(SOC_FC_HEADER |
1515                             sf->sf_sochandle->fcal_portno);
1516                         fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3;
1517                         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1;
1518                         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0;
1519                         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0;
1520                         fpkt->fcal_socal_request.sr_dataseg[0].fc_base =
1521                             (uint32_t)cmd->cmd_dmac;
1522                         fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
1523                             sizeof (struct fcp_cmd);
1524                         fpkt->fcal_socal_request.sr_dataseg[1].fc_base =
1525                             (uint32_t)cmd->cmd_rsp_dmac;
1526                         fpkt->fcal_socal_request.sr_dataseg[1].fc_count =
1527                             FCP_MAX_RSP_IU_SIZE;
1528 
1529                         /* Fill in the Fabric Channel Header */
1530                         hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
1531                         hp->r_ctl = R_CTL_COMMAND;
1532                         hp->type = TYPE_SCSI_FCP;
1533                         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
1534                         hp->reserved1 = 0;
1535                         hp->seq_id = 0;
1536                         hp->df_ctl  = 0;
1537                         hp->seq_cnt = 0;
1538                         hp->ox_id = 0xffff;
1539                         hp->rx_id = 0xffff;
1540                         hp->ro = 0;
1541 
1542                         /* Establish the LUN */
1543                         bcopy((caddr_t)&target->sft_lun.b,
1544                             (caddr_t)&cmd->cmd_block->fcp_ent_addr,
1545                             FCP_LUN_SIZE);
1546                         *((int32_t *)&cmd->cmd_block->fcp_cntl) = 0;
1547                 }
1548                 cmd->cmd_pkt->pkt_cdbp = cmd->cmd_block->fcp_cdb;
1549 
1550                 mutex_enter(&target->sft_pkt_mutex);
1551 
1552                 target->sft_pkt_tail->cmd_forw = cmd;
1553                 cmd->cmd_back = target->sft_pkt_tail;
1554                 cmd->cmd_forw = (struct sf_pkt *)&target->sft_pkt_head;
1555                 target->sft_pkt_tail = cmd;
1556 
1557                 mutex_exit(&target->sft_pkt_mutex);
1558                 new_cmd = cmd;          /* for later cleanup if needed */
1559         } else {
1560                 /* pkt already exists -- just a request for DMA allocation */
1561                 cmd = PKT2CMD(pkt);
1562                 fpkt = cmd->cmd_fp_pkt;
1563         }
1564 
1565         /* zero cdb (bzero is too slow) */
1566         bzero((caddr_t)cmd->cmd_pkt->pkt_cdbp, cmdlen);
1567 
1568         /*
1569          * Second step of sf_scsi_init_pkt:  dma allocation
1570          * Set up dma info
1571          */
1572         if ((bp != NULL) && (bp->b_bcount != 0)) {
1573                 int cmd_flags, dma_flags;
1574                 int rval = 0;
1575                 uint_t dmacookie_count;
1576 
1577                 /* there is a buffer and some data to transfer */
1578 
1579                 /* set up command and DMA flags */
1580                 cmd_flags = cmd->cmd_flags;
1581                 if (bp->b_flags & B_READ) {
1582                         /* a read */
1583                         cmd_flags &= ~CFLAG_DMASEND;
1584                         dma_flags = DDI_DMA_READ;
1585                 } else {
1586                         /* a write */
1587                         cmd_flags |= CFLAG_DMASEND;
1588                         dma_flags = DDI_DMA_WRITE;
1589                 }
1590                 if (flags & PKT_CONSISTENT) {
1591                         cmd_flags |= CFLAG_CMDIOPB;
1592                         dma_flags |= DDI_DMA_CONSISTENT;
1593                 }
1594 
1595                 /* ensure we have a DMA handle */
1596                 if (cmd->cmd_dmahandle == NULL) {
1597                         rval = ddi_dma_alloc_handle(sf->sf_dip,
1598                             sf->sf_sochandle->fcal_dmaattr, callback, arg,
1599                             &cmd->cmd_dmahandle);
1600                 }
1601 
1602                 if (rval == 0) {
1603                         /* bind our DMA handle to our buffer */
1604                         rval = ddi_dma_buf_bind_handle(cmd->cmd_dmahandle, bp,
1605                             dma_flags, callback, arg, &cmd->cmd_dmacookie,
1606                             &dmacookie_count);
1607                 }
1608 
1609                 if (rval != 0) {
1610                         /* DMA failure */
1611                         SF_DEBUG(2, (sf, CE_CONT, "ddi_dma_buf.. failed\n"));
1612                         switch (rval) {
1613                         case DDI_DMA_NORESOURCES:
1614                                 bioerror(bp, 0);
1615                                 break;
1616                         case DDI_DMA_BADATTR:
1617                         case DDI_DMA_NOMAPPING:
1618                                 bioerror(bp, EFAULT);
1619                                 break;
1620                         case DDI_DMA_TOOBIG:
1621                         default:
1622                                 bioerror(bp, EINVAL);
1623                                 break;
1624                         }
1625                         /* clear valid flag */
1626                         cmd->cmd_flags = cmd_flags & ~CFLAG_DMAVALID;
1627                         if (new_cmd != NULL) {
1628                                 /* destroy packet if we just created it */
1629                                 sf_scsi_destroy_pkt(ap, new_cmd->cmd_pkt);
1630                         }
1631                         return (NULL);
1632                 }
1633 
1634                 ASSERT(dmacookie_count == 1);
1635                 /* set up amt to transfer and set valid flag */
1636                 cmd->cmd_dmacount = bp->b_bcount;
1637                 cmd->cmd_flags = cmd_flags | CFLAG_DMAVALID;
1638 
1639                 ASSERT(cmd->cmd_dmahandle != NULL);
1640         }
1641 
1642         /* set up FC-AL packet */
1643         fcmd = cmd->cmd_block;
1644 
1645         if (cmd->cmd_flags & CFLAG_DMAVALID) {
1646                 if (cmd->cmd_flags & CFLAG_DMASEND) {
1647                         /* DMA write */
1648                         fcmd->fcp_cntl.cntl_read_data = 0;
1649                         fcmd->fcp_cntl.cntl_write_data = 1;
1650                         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
1651                             CQ_TYPE_IO_WRITE;
1652                 } else {
1653                         /* DMA read */
1654                         fcmd->fcp_cntl.cntl_read_data = 1;
1655                         fcmd->fcp_cntl.cntl_write_data = 0;
1656                         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
1657                             CQ_TYPE_IO_READ;
1658                 }
1659                 fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
1660                     (uint32_t)cmd->cmd_dmacookie.dmac_address;
1661                 fpkt->fcal_socal_request.sr_dataseg[2].fc_count =
1662                     cmd->cmd_dmacookie.dmac_size;
1663                 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
1664                 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
1665                     cmd->cmd_dmacookie.dmac_size;
1666                 fcmd->fcp_data_len = cmd->cmd_dmacookie.dmac_size;
1667         } else {
1668                 /* not a read or write */
1669                 fcmd->fcp_cntl.cntl_read_data = 0;
1670                 fcmd->fcp_cntl.cntl_write_data = 0;
1671                 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE;
1672                 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2;
1673                 fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
1674                     sizeof (struct fcp_cmd);
1675                 fcmd->fcp_data_len = 0;
1676         }
1677         fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
1678 
1679         return (cmd->cmd_pkt);
1680 }
1681 
1682 
1683 /*
1684  * destroy a SCSI packet -- called internally and by the transport
1685  */
1686 static void
1687 sf_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1688 {
1689         struct sf_pkt *cmd = PKT2CMD(pkt);
1690         struct sf *sf = ADDR2SF(ap);
1691         struct sf_target *target = ADDR2TARGET(ap);
1692         struct fcal_packet      *fpkt = cmd->cmd_fp_pkt;
1693 
1694 
1695         if (cmd->cmd_flags & CFLAG_DMAVALID) {
1696                 /* DMA was set up -- clean up */
1697                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
1698                 cmd->cmd_flags ^= CFLAG_DMAVALID;
1699         }
1700 
1701         /* take this packet off the doubly-linked list */
1702         mutex_enter(&target->sft_pkt_mutex);
1703         cmd->cmd_back->cmd_forw = cmd->cmd_forw;
1704         cmd->cmd_forw->cmd_back = cmd->cmd_back;
1705         mutex_exit(&target->sft_pkt_mutex);
1706 
1707         fpkt->fcal_pkt_flags = 0;
1708         /* free the packet */
1709         if ((cmd->cmd_flags &
1710             (CFLAG_FREE | CFLAG_PRIVEXTERN | CFLAG_SCBEXTERN)) == 0) {
1711                 /* just a regular packet */
1712                 ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
1713                 cmd->cmd_flags = CFLAG_FREE;
1714                 kmem_cache_free(sf->sf_pkt_cache, (void *)cmd);
1715         } else {
1716                 /* a packet with extra memory */
1717                 sf_pkt_destroy_extern(sf, cmd);
1718         }
1719 }
1720 
1721 
1722 /*
1723  * called by transport to unbind DMA handle
1724  */
1725 /* ARGSUSED */
1726 static void
1727 sf_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
1728 {
1729         struct sf_pkt *cmd = PKT2CMD(pkt);
1730 
1731 
1732         if (cmd->cmd_flags & CFLAG_DMAVALID) {
1733                 (void) ddi_dma_unbind_handle(cmd->cmd_dmahandle);
1734                 cmd->cmd_flags ^= CFLAG_DMAVALID;
1735         }
1736 
1737 }
1738 
1739 
1740 /*
1741  * called by transport to synchronize CPU and I/O views of memory
1742  */
1743 /* ARGSUSED */
1744 static void
1745 sf_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1746 {
1747         struct sf_pkt *cmd = PKT2CMD(pkt);
1748 
1749 
1750         if (cmd->cmd_flags & CFLAG_DMAVALID) {
1751                 if (ddi_dma_sync(cmd->cmd_dmahandle, (off_t)0, (size_t)0,
1752                     (cmd->cmd_flags & CFLAG_DMASEND) ?
1753                     DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU) !=
1754                     DDI_SUCCESS) {
1755                         cmn_err(CE_WARN, "sf: sync pkt failed");
1756                 }
1757         }
1758 }
1759 
1760 
1761 /*
1762  * routine for reset notification setup, to register or cancel. -- called
1763  * by transport
1764  */
1765 static int
1766 sf_scsi_reset_notify(struct scsi_address *ap, int flag,
1767     void (*callback)(caddr_t), caddr_t arg)
1768 {
1769         struct sf       *sf = ADDR2SF(ap);
1770 
1771         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
1772             &sf->sf_mutex, &sf->sf_reset_notify_listf));
1773 }
1774 
1775 
1776 /*
1777  * called by transport to get port WWN property (except sun4u)
1778  */
1779 /* ARGSUSED */
1780 static int
1781 sf_scsi_get_name(struct scsi_device *sd, char *name, int len)
1782 {
1783         char tbuf[(FC_WWN_SIZE*2)+1];
1784         unsigned char wwn[FC_WWN_SIZE];
1785         int i, lun;
1786         dev_info_t *tgt_dip;
1787 
1788         tgt_dip = sd->sd_dev;
1789         i = sizeof (wwn);
1790         if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1791             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, PORT_WWN_PROP,
1792             (caddr_t)&wwn, &i) != DDI_SUCCESS) {
1793                 name[0] = '\0';
1794                 return (0);
1795         }
1796         i = sizeof (lun);
1797         if (ddi_prop_op(DDI_DEV_T_ANY, tgt_dip, PROP_LEN_AND_VAL_BUF,
1798             DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "lun",
1799             (caddr_t)&lun, &i) != DDI_SUCCESS) {
1800                 name[0] = '\0';
1801                 return (0);
1802         }
1803         for (i = 0; i < FC_WWN_SIZE; i++)
1804                 (void) sprintf(&tbuf[i << 1], "%02x", wwn[i]);
1805         (void) sprintf(name, "w%s,%x", tbuf, lun);
1806         return (1);
1807 }
1808 
1809 
1810 /*
1811  * called by transport to get target soft AL-PA (except sun4u)
1812  */
1813 /* ARGSUSED */
1814 static int
1815 sf_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
1816 {
1817         struct sf_target *target = ADDR2TARGET(&sd->sd_address);
1818 
1819         if (target == NULL)
1820                 return (0);
1821 
1822         (void) sprintf(name, "%x", target->sft_al_pa);
1823         return (1);
1824 }
1825 
1826 
1827 /*
1828  * add to the command/response buffer pool for this sf instance
1829  */
1830 static int
1831 sf_add_cr_pool(struct sf *sf)
1832 {
1833         int             cmd_buf_size;
1834         size_t          real_cmd_buf_size;
1835         int             rsp_buf_size;
1836         size_t          real_rsp_buf_size;
1837         uint_t          i, ccount;
1838         struct sf_cr_pool       *ptr;
1839         struct sf_cr_free_elem *cptr;
1840         caddr_t dptr, eptr;
1841         ddi_dma_cookie_t        cmd_cookie;
1842         ddi_dma_cookie_t        rsp_cookie;
1843         int             cmd_bound = FALSE, rsp_bound = FALSE;
1844 
1845 
1846         /* allocate room for the pool */
1847         if ((ptr = kmem_zalloc(sizeof (struct sf_cr_pool), KM_NOSLEEP)) ==
1848             NULL) {
1849                 return (DDI_FAILURE);
1850         }
1851 
1852         /* allocate a DMA handle for the command pool */
1853         if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
1854             DDI_DMA_DONTWAIT, NULL, &ptr->cmd_dma_handle) != DDI_SUCCESS) {
1855                 goto fail;
1856         }
1857 
1858         /*
1859          * Get a piece of memory in which to put commands
1860          */
1861         cmd_buf_size = (sizeof (struct fcp_cmd) * SF_ELEMS_IN_POOL + 7) & ~7;
1862         if (ddi_dma_mem_alloc(ptr->cmd_dma_handle, cmd_buf_size,
1863             sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
1864             DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->cmd_base,
1865             &real_cmd_buf_size, &ptr->cmd_acc_handle) != DDI_SUCCESS) {
1866                 goto fail;
1867         }
1868 
1869         /* bind the DMA handle to an address */
1870         if (ddi_dma_addr_bind_handle(ptr->cmd_dma_handle, NULL,
1871             ptr->cmd_base, real_cmd_buf_size,
1872             DDI_DMA_WRITE | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
1873             NULL, &cmd_cookie, &ccount) != DDI_DMA_MAPPED) {
1874                 goto fail;
1875         }
1876         cmd_bound = TRUE;
1877         /* ensure only one cookie was allocated */
1878         if (ccount != 1) {
1879                 goto fail;
1880         }
1881 
1882         /* allocate a DMA handle for the response pool */
1883         if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
1884             DDI_DMA_DONTWAIT, NULL, &ptr->rsp_dma_handle) != DDI_SUCCESS) {
1885                 goto fail;
1886         }
1887 
1888         /*
1889          * Get a piece of memory in which to put responses
1890          */
1891         rsp_buf_size = FCP_MAX_RSP_IU_SIZE * SF_ELEMS_IN_POOL;
1892         if (ddi_dma_mem_alloc(ptr->rsp_dma_handle, rsp_buf_size,
1893             sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
1894             DDI_DMA_DONTWAIT, NULL, (caddr_t *)&ptr->rsp_base,
1895             &real_rsp_buf_size, &ptr->rsp_acc_handle) != DDI_SUCCESS) {
1896                 goto fail;
1897         }
1898 
1899         /* bind the DMA handle to an address */
1900         if (ddi_dma_addr_bind_handle(ptr->rsp_dma_handle, NULL,
1901             ptr->rsp_base, real_rsp_buf_size,
1902             DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
1903             NULL, &rsp_cookie, &ccount) != DDI_DMA_MAPPED) {
1904                 goto fail;
1905         }
1906         rsp_bound = TRUE;
1907         /* ensure only one cookie was allocated */
1908         if (ccount != 1) {
1909                 goto fail;
1910         }
1911 
1912         /*
1913          * Generate a (cmd/rsp structure) free list
1914          */
1915         /* ensure ptr points to start of long word (8-byte block) */
1916         dptr = (caddr_t)((uintptr_t)(ptr->cmd_base) + 7 & ~7);
1917         /* keep track of actual size after moving pointer */
1918         real_cmd_buf_size -= (dptr - ptr->cmd_base);
1919         eptr = ptr->rsp_base;
1920 
1921         /* set actual total number of entries */
1922         ptr->ntot = min((real_cmd_buf_size / sizeof (struct fcp_cmd)),
1923             (real_rsp_buf_size / FCP_MAX_RSP_IU_SIZE));
1924         ptr->nfree = ptr->ntot;
1925         ptr->free = (struct sf_cr_free_elem *)ptr->cmd_base;
1926         ptr->sf = sf;
1927 
1928         /* set up DMA for each pair of entries */
1929         i = 0;
1930         while (i < ptr->ntot) {
1931                 cptr = (struct sf_cr_free_elem *)dptr;
1932                 dptr += sizeof (struct fcp_cmd);
1933 
1934                 cptr->next = (struct sf_cr_free_elem *)dptr;
1935                 cptr->rsp = eptr;
1936 
1937                 cptr->cmd_dmac = cmd_cookie.dmac_address +
1938                     (uint32_t)((caddr_t)cptr - ptr->cmd_base);
1939 
1940                 cptr->rsp_dmac = rsp_cookie.dmac_address +
1941                     (uint32_t)((caddr_t)eptr - ptr->rsp_base);
1942 
1943                 eptr += FCP_MAX_RSP_IU_SIZE;
1944                 i++;
1945         }
1946 
1947         /* terminate the list */
1948         cptr->next = NULL;
1949 
1950         /* add this list at front of current one */
1951         mutex_enter(&sf->sf_cr_mutex);
1952         ptr->next = sf->sf_cr_pool;
1953         sf->sf_cr_pool = ptr;
1954         sf->sf_cr_pool_cnt++;
1955         mutex_exit(&sf->sf_cr_mutex);
1956 
1957         return (DDI_SUCCESS);
1958 
1959 fail:
1960         /* we failed so clean up */
1961         if (ptr->cmd_dma_handle != NULL) {
1962                 if (cmd_bound) {
1963                         (void) ddi_dma_unbind_handle(ptr->cmd_dma_handle);
1964                 }
1965                 ddi_dma_free_handle(&ptr->cmd_dma_handle);
1966         }
1967 
1968         if (ptr->rsp_dma_handle != NULL) {
1969                 if (rsp_bound) {
1970                         (void) ddi_dma_unbind_handle(ptr->rsp_dma_handle);
1971                 }
1972                 ddi_dma_free_handle(&ptr->rsp_dma_handle);
1973         }
1974 
1975         if (ptr->cmd_base != NULL) {
1976                 ddi_dma_mem_free(&ptr->cmd_acc_handle);
1977         }
1978 
1979         if (ptr->rsp_base != NULL) {
1980                 ddi_dma_mem_free(&ptr->rsp_acc_handle);
1981         }
1982 
1983         kmem_free((caddr_t)ptr, sizeof (struct sf_cr_pool));
1984         return (DDI_FAILURE);
1985 }
1986 
1987 
1988 /*
1989  * allocate a command/response buffer from the pool, allocating more
1990  * in the pool as needed
1991  */
1992 static int
1993 sf_cr_alloc(struct sf *sf, struct sf_pkt *cmd, int (*func)())
1994 {
1995         struct sf_cr_pool *ptr;
1996         struct sf_cr_free_elem *cptr;
1997 
1998 
1999         mutex_enter(&sf->sf_cr_mutex);
2000 
2001 try_again:
2002 
2003         /* find a free buffer in the existing pool */
2004         ptr = sf->sf_cr_pool;
2005         while (ptr != NULL) {
2006                 if (ptr->nfree != 0) {
2007                         ptr->nfree--;
2008                         break;
2009                 } else {
2010                         ptr = ptr->next;
2011                 }
2012         }
2013 
2014         /* did we find a free buffer ? */
2015         if (ptr != NULL) {
2016                 /* we found a free buffer -- take it off the free list */
2017                 cptr = ptr->free;
2018                 ptr->free = cptr->next;
2019                 mutex_exit(&sf->sf_cr_mutex);
2020                 /* set up the command to use the buffer pair */
2021                 cmd->cmd_block = (struct fcp_cmd *)cptr;
2022                 cmd->cmd_dmac = cptr->cmd_dmac;
2023                 cmd->cmd_rsp_dmac = cptr->rsp_dmac;
2024                 cmd->cmd_rsp_block = (struct fcp_rsp *)cptr->rsp;
2025                 cmd->cmd_cr_pool = ptr;
2026                 return (DDI_SUCCESS);           /* success */
2027         }
2028 
2029         /* no free buffer available -- can we allocate more ? */
2030         if (sf->sf_cr_pool_cnt < SF_CR_POOL_MAX) {
2031                 /* we need to allocate more buffer pairs */
2032                 if (sf->sf_cr_flag) {
2033                         /* somebody already allocating for this instance */
2034                         if (func == SLEEP_FUNC) {
2035                                 /* user wants to wait */
2036                                 cv_wait(&sf->sf_cr_cv, &sf->sf_cr_mutex);
2037                                 /* we've been woken so go try again */
2038                                 goto try_again;
2039                         }
2040                         /* user does not want to wait */
2041                         mutex_exit(&sf->sf_cr_mutex);
2042                         sf->sf_stats.cralloc_failures++;
2043                         return (DDI_FAILURE);   /* give up */
2044                 }
2045                 /* set flag saying we're allocating */
2046                 sf->sf_cr_flag = 1;
2047                 mutex_exit(&sf->sf_cr_mutex);
2048                 /* add to our pool */
2049                 if (sf_add_cr_pool(sf) != DDI_SUCCESS) {
2050                         /* couldn't add to our pool for some reason */
2051                         mutex_enter(&sf->sf_cr_mutex);
2052                         sf->sf_cr_flag = 0;
2053                         cv_broadcast(&sf->sf_cr_cv);
2054                         mutex_exit(&sf->sf_cr_mutex);
2055                         sf->sf_stats.cralloc_failures++;
2056                         return (DDI_FAILURE);   /* give up */
2057                 }
2058                 /*
2059                  * clear flag saying we're allocating and tell all other
2060                  * that care
2061                  */
2062                 mutex_enter(&sf->sf_cr_mutex);
2063                 sf->sf_cr_flag = 0;
2064                 cv_broadcast(&sf->sf_cr_cv);
2065                 /* now that we have more buffers try again */
2066                 goto try_again;
2067         }
2068 
2069         /* we don't have room to allocate any more buffers */
2070         mutex_exit(&sf->sf_cr_mutex);
2071         sf->sf_stats.cralloc_failures++;
2072         return (DDI_FAILURE);                   /* give up */
2073 }
2074 
2075 
2076 /*
2077  * free a cmd/response buffer pair in our pool
2078  */
2079 static void
2080 sf_cr_free(struct sf_cr_pool *cp, struct sf_pkt *cmd)
2081 {
2082         struct sf *sf = cp->sf;
2083         struct sf_cr_free_elem *elem;
2084 
2085         elem = (struct sf_cr_free_elem *)cmd->cmd_block;
2086         elem->rsp = (caddr_t)cmd->cmd_rsp_block;
2087         elem->cmd_dmac = cmd->cmd_dmac;
2088         elem->rsp_dmac = cmd->cmd_rsp_dmac;
2089 
2090         mutex_enter(&sf->sf_cr_mutex);
2091         cp->nfree++;
2092         ASSERT(cp->nfree <= cp->ntot);
2093 
2094         elem->next = cp->free;
2095         cp->free = elem;
2096         mutex_exit(&sf->sf_cr_mutex);
2097 }
2098 
2099 
2100 /*
2101  * free our pool of cmd/response buffers
2102  */
2103 static void
2104 sf_crpool_free(struct sf *sf)
2105 {
2106         struct sf_cr_pool *cp, *prev;
2107 
2108         prev = NULL;
2109         mutex_enter(&sf->sf_cr_mutex);
2110         cp = sf->sf_cr_pool;
2111         while (cp != NULL) {
2112                 if (cp->nfree == cp->ntot) {
2113                         if (prev != NULL) {
2114                                 prev->next = cp->next;
2115                         } else {
2116                                 sf->sf_cr_pool = cp->next;
2117                         }
2118                         sf->sf_cr_pool_cnt--;
2119                         mutex_exit(&sf->sf_cr_mutex);
2120 
2121                         (void) ddi_dma_unbind_handle(cp->cmd_dma_handle);
2122                         ddi_dma_free_handle(&cp->cmd_dma_handle);
2123                         (void) ddi_dma_unbind_handle(cp->rsp_dma_handle);
2124                         ddi_dma_free_handle(&cp->rsp_dma_handle);
2125                         ddi_dma_mem_free(&cp->cmd_acc_handle);
2126                         ddi_dma_mem_free(&cp->rsp_acc_handle);
2127                         kmem_free((caddr_t)cp, sizeof (struct sf_cr_pool));
2128                         return;
2129                 }
2130                 prev = cp;
2131                 cp = cp->next;
2132         }
2133         mutex_exit(&sf->sf_cr_mutex);
2134 }
2135 
2136 
2137 /* ARGSUSED */
2138 static int
2139 sf_kmem_cache_constructor(void *buf, void *arg, int size)
2140 {
2141         struct sf_pkt *cmd = buf;
2142 
2143         mutex_init(&cmd->cmd_abort_mutex, NULL, MUTEX_DRIVER, NULL);
2144         cmd->cmd_block = NULL;
2145         cmd->cmd_dmahandle = NULL;
2146         return (0);
2147 }
2148 
2149 
2150 /* ARGSUSED */
2151 static void
2152 sf_kmem_cache_destructor(void *buf, void *size)
2153 {
2154         struct sf_pkt *cmd = buf;
2155 
2156         if (cmd->cmd_dmahandle != NULL) {
2157                 ddi_dma_free_handle(&cmd->cmd_dmahandle);
2158         }
2159 
2160         if (cmd->cmd_block != NULL) {
2161                 sf_cr_free(cmd->cmd_cr_pool, cmd);
2162         }
2163         mutex_destroy(&cmd->cmd_abort_mutex);
2164 }
2165 
2166 
2167 /*
2168  * called by transport when a state change occurs
2169  */
2170 static void
2171 sf_statec_callback(void *arg, int msg)
2172 {
2173         struct sf *sf = (struct sf *)arg;
2174         struct sf_target        *target;
2175         int i;
2176         struct sf_pkt *cmd;
2177         struct scsi_pkt *pkt;
2178 
2179 
2180 
2181         switch (msg) {
2182 
2183         case FCAL_STATUS_LOOP_ONLINE: {
2184                 uchar_t         al_pa;          /* to save AL-PA */
2185                 int             ret;            /* ret value from getmap */
2186                 int             lip_cnt;        /* to save current count */
2187                 int             cnt;            /* map length */
2188 
2189                 /*
2190                  * the loop has gone online
2191                  */
2192                 SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop online\n",
2193                     ddi_get_instance(sf->sf_dip)));
2194                 mutex_enter(&sf->sf_mutex);
2195                 sf->sf_lip_cnt++;
2196                 sf->sf_state = SF_STATE_ONLINING;
2197                 mutex_exit(&sf->sf_mutex);
2198 
2199                 /* scan each target hash queue */
2200                 for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
2201                         target = sf->sf_wwn_lists[i];
2202                         while (target != NULL) {
2203                                 /*
2204                                  * foreach target, if it's not offline then
2205                                  * mark it as busy
2206                                  */
2207                                 mutex_enter(&target->sft_mutex);
2208                                 if (!(target->sft_state & SF_TARGET_OFFLINE))
2209                                         target->sft_state |= (SF_TARGET_BUSY
2210                                             | SF_TARGET_MARK);
2211 #ifdef DEBUG
2212                                 /*
2213                                  * for debugging, print out info on any
2214                                  * pending commands (left hanging)
2215                                  */
2216                                 cmd = target->sft_pkt_head;
2217                                 while (cmd != (struct sf_pkt *)&target->
2218                                     sft_pkt_head) {
2219                                         if (cmd->cmd_state ==
2220                                             SF_STATE_ISSUED) {
2221                                                 SF_DEBUG(1, (sf, CE_CONT,
2222                                                     "cmd 0x%p pending "
2223                                                     "after lip\n",
2224                                                     (void *)cmd->cmd_fp_pkt));
2225                                         }
2226                                         cmd = cmd->cmd_forw;
2227                                 }
2228 #endif
2229                                 mutex_exit(&target->sft_mutex);
2230                                 target = target->sft_next;
2231                         }
2232                 }
2233 
2234                 /*
2235                  * since the loop has just gone online get a new map from
2236                  * the transport
2237                  */
2238                 if ((ret = soc_get_lilp_map(sf->sf_sochandle, sf->sf_socp,
2239                     sf->sf_sochandle->fcal_portno, (uint32_t)sf->
2240                     sf_lilp_dmacookie.dmac_address, 1)) != FCAL_SUCCESS) {
2241                         if (sf_core && (sf_core & SF_CORE_LILP_FAILED)) {
2242                                 (void) soc_take_core(sf->sf_sochandle,
2243                                     sf->sf_socp);
2244                                 sf_core = 0;
2245                         }
2246                         sf_log(sf, CE_WARN,
2247                             "!soc lilp map failed status=0x%x\n", ret);
2248                         mutex_enter(&sf->sf_mutex);
2249                         sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
2250                         sf->sf_lip_cnt++;
2251                         sf->sf_state = SF_STATE_OFFLINE;
2252                         mutex_exit(&sf->sf_mutex);
2253                         return;
2254                 }
2255 
2256                 /* ensure consistent view of DMA memory */
2257                 (void) ddi_dma_sync(sf->sf_lilp_dmahandle, (off_t)0, (size_t)0,
2258                     DDI_DMA_SYNC_FORKERNEL);
2259 
2260                 /* how many entries in map ? */
2261                 cnt = sf->sf_lilp_map->lilp_length;
2262                 if (cnt >= SF_MAX_LILP_ENTRIES) {
2263                         sf_log(sf, CE_WARN, "invalid lilp map\n");
2264                         return;
2265                 }
2266 
2267                 mutex_enter(&sf->sf_mutex);
2268                 sf->sf_device_count = cnt - 1;
2269                 sf->sf_al_pa = sf->sf_lilp_map->lilp_myalpa;
2270                 lip_cnt = sf->sf_lip_cnt;
2271                 al_pa = sf->sf_al_pa;
2272 
2273                 SF_DEBUG(1, (sf, CE_CONT,
2274                     "!lilp map has %d entries, al_pa is %x\n", cnt, al_pa));
2275 
2276                 /*
2277                  * since the last entry of the map may be mine (common) check
2278                  * for that, and if it is we have one less entry to look at
2279                  */
2280                 if (sf->sf_lilp_map->lilp_alpalist[cnt-1] == al_pa) {
2281                         cnt--;
2282                 }
2283                 /* If we didn't get a valid loop map enable all targets */
2284                 if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) {
2285                         for (i = 0; i < sizeof (sf_switch_to_alpa); i++)
2286                                 sf->sf_lilp_map->lilp_alpalist[i] =
2287                                     sf_switch_to_alpa[i];
2288                         cnt = i;
2289                         sf->sf_device_count = cnt - 1;
2290                 }
2291                 if (sf->sf_device_count == 0) {
2292                         sf_finish_init(sf, lip_cnt);
2293                         mutex_exit(&sf->sf_mutex);
2294                         break;
2295                 }
2296                 mutex_exit(&sf->sf_mutex);
2297 
2298                 SF_DEBUG(2, (sf, CE_WARN,
2299                     "!statec_callback: starting with %d targets\n",
2300                     sf->sf_device_count));
2301 
2302                 /* scan loop map, logging into all ports (except mine) */
2303                 for (i = 0; i < cnt; i++) {
2304                         SF_DEBUG(1, (sf, CE_CONT,
2305                             "!lilp map entry %d = %x,%x\n", i,
2306                             sf->sf_lilp_map->lilp_alpalist[i],
2307                             sf_alpa_to_switch[
2308                             sf->sf_lilp_map->lilp_alpalist[i]]));
2309                         /* is this entry for somebody else ? */
2310                         if (sf->sf_lilp_map->lilp_alpalist[i] != al_pa) {
2311                                 /* do a PLOGI to this port */
2312                                 if (!sf_login(sf, LA_ELS_PLOGI,
2313                                     sf->sf_lilp_map->lilp_alpalist[i],
2314                                     sf->sf_lilp_map->lilp_alpalist[cnt-1],
2315                                     lip_cnt)) {
2316                                         /* a problem logging in */
2317                                         mutex_enter(&sf->sf_mutex);
2318                                         if (lip_cnt == sf->sf_lip_cnt) {
2319                                                 /*
2320                                                  * problem not from a new LIP
2321                                                  */
2322                                                 sf->sf_device_count--;
2323                                                 ASSERT(sf->sf_device_count
2324                                                     >= 0);
2325                                                 if (sf->sf_device_count == 0) {
2326                                                         sf_finish_init(sf,
2327                                                             lip_cnt);
2328                                                 }
2329                                         }
2330                                         mutex_exit(&sf->sf_mutex);
2331                                 }
2332                         }
2333                 }
2334                 break;
2335         }
2336 
2337         case FCAL_STATUS_ERR_OFFLINE:
2338                 /*
2339                  * loop has gone offline due to an error
2340                  */
2341                 SF_DEBUG(1, (sf, CE_CONT, "sf%d: loop offline\n",
2342                     ddi_get_instance(sf->sf_dip)));
2343                 mutex_enter(&sf->sf_mutex);
2344                 sf->sf_lip_cnt++;
2345                 sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
2346                 if (!sf->sf_online_timer) {
2347                         sf->sf_online_timer = sf_watchdog_time +
2348                             SF_ONLINE_TIMEOUT;
2349                 }
2350                 /*
2351                  * if we are suspended, preserve the SF_STATE_SUSPENDED flag,
2352                  * since throttling logic in sf_watch() depends on
2353                  * preservation of this flag while device is suspended
2354                  */
2355                 if (sf->sf_state & SF_STATE_SUSPENDED) {
2356                         sf->sf_state |= SF_STATE_OFFLINE;
2357                         SF_DEBUG(1, (sf, CE_CONT,
2358                             "sf_statec_callback, sf%d: "
2359                             "got FCAL_STATE_OFFLINE during DDI_SUSPEND\n",
2360                             ddi_get_instance(sf->sf_dip)));
2361                 } else {
2362                         sf->sf_state = SF_STATE_OFFLINE;
2363                 }
2364 
2365                 /* scan each possible target on the loop */
2366                 for (i = 0; i < sf_max_targets; i++) {
2367                         target = sf->sf_targets[i];
2368                         while (target != NULL) {
2369                                 mutex_enter(&target->sft_mutex);
2370                                 if (!(target->sft_state & SF_TARGET_OFFLINE))
2371                                         target->sft_state |= (SF_TARGET_BUSY
2372                                             | SF_TARGET_MARK);
2373                                 mutex_exit(&target->sft_mutex);
2374                                 target = target->sft_next_lun;
2375                         }
2376                 }
2377                 mutex_exit(&sf->sf_mutex);
2378                 break;
2379 
2380         case FCAL_STATE_RESET: {
2381                 struct sf_els_hdr       *privp; /* ptr to private list */
2382                 struct sf_els_hdr       *tmpp1; /* tmp prev hdr ptr */
2383                 struct sf_els_hdr       *tmpp2; /* tmp next hdr ptr */
2384                 struct sf_els_hdr       *head;  /* to save our private list */
2385                 struct fcal_packet      *fpkt;  /* ptr to pkt in hdr */
2386 
2387                 /*
2388                  * a transport reset
2389                  */
2390                 SF_DEBUG(1, (sf, CE_CONT, "!sf%d: soc reset\n",
2391                     ddi_get_instance(sf->sf_dip)));
2392                 tmpp1 = head = NULL;
2393                 mutex_enter(&sf->sf_mutex);
2394                 sf->sf_lip_cnt++;
2395                 sf->sf_timer = sf_watchdog_time + SF_RESET_TIMEOUT;
2396                 /*
2397                  * if we are suspended, preserve the SF_STATE_SUSPENDED flag,
2398                  * since throttling logic in sf_watch() depends on
2399                  * preservation of this flag while device is suspended
2400                  */
2401                 if (sf->sf_state & SF_STATE_SUSPENDED) {
2402                         sf->sf_state |= SF_STATE_OFFLINE;
2403                         SF_DEBUG(1, (sf, CE_CONT,
2404                             "sf_statec_callback, sf%d: "
2405                             "got FCAL_STATE_RESET during DDI_SUSPEND\n",
2406                             ddi_get_instance(sf->sf_dip)));
2407                 } else {
2408                         sf->sf_state = SF_STATE_OFFLINE;
2409                 }
2410 
2411                 /*
2412                  * scan each possible target on the loop, looking for targets
2413                  * that need callbacks ran
2414                  */
2415                 for (i = 0; i < sf_max_targets; i++) {
2416                         target = sf->sf_targets[i];
2417                         while (target != NULL) {
2418                                 if (!(target->sft_state & SF_TARGET_OFFLINE)) {
2419                                         target->sft_state |= (SF_TARGET_BUSY
2420                                             | SF_TARGET_MARK);
2421                                         mutex_exit(&sf->sf_mutex);
2422                                         /*
2423                                          * run remove event callbacks for lun
2424                                          *
2425                                          * We have a nasty race condition here
2426                                          * 'cause we're dropping this mutex to
2427                                          * run the callback and expect the
2428                                          * linked list to be the same.
2429                                          */
2430                                         (void) ndi_event_retrieve_cookie(
2431                                             sf->sf_event_hdl, target->sft_dip,
2432                                             FCAL_REMOVE_EVENT, &sf_remove_eid,
2433                                             NDI_EVENT_NOPASS);
2434                                         (void) ndi_event_run_callbacks(
2435                                             sf->sf_event_hdl,
2436                                             target->sft_dip,
2437                                             sf_remove_eid, NULL);
2438                                         mutex_enter(&sf->sf_mutex);
2439                                 }
2440                                 target = target->sft_next_lun;
2441                         }
2442                 }
2443 
2444                 /*
2445                  * scan for ELS commands that are in transport, not complete,
2446                  * and have a valid timeout, building a private list
2447                  */
2448                 privp = sf->sf_els_list;
2449                 while (privp != NULL) {
2450                         fpkt = privp->fpkt;
2451                         if ((fpkt->fcal_cmd_state & FCAL_CMD_IN_TRANSPORT) &&
2452                             (!(fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE)) &&
2453                             (privp->timeout != SF_INVALID_TIMEOUT)) {
2454                                 /*
2455                                  * cmd in transport && not complete &&
2456                                  * timeout valid
2457                                  *
2458                                  * move this entry from ELS input list to our
2459                                  * private list
2460                                  */
2461 
2462                                 tmpp2 = privp->next; /* save ptr to next */
2463 
2464                                 /* push this on private list head */
2465                                 privp->next = head;
2466                                 head = privp;
2467 
2468                                 /* remove this entry from input list */
2469                                 if (tmpp1 != NULL) {
2470                                         /*
2471                                          * remove this entry from somewhere in
2472                                          * the middle of the list
2473                                          */
2474                                         tmpp1->next = tmpp2;
2475                                         if (tmpp2 != NULL) {
2476                                                 tmpp2->prev = tmpp1;
2477                                         }
2478                                 } else {
2479                                         /*
2480                                          * remove this entry from the head
2481                                          * of the list
2482                                          */
2483                                         sf->sf_els_list = tmpp2;
2484                                         if (tmpp2 != NULL) {
2485                                                 tmpp2->prev = NULL;
2486                                         }
2487                                 }
2488                                 privp = tmpp2;  /* skip to next entry */
2489                         } else {
2490                                 tmpp1 = privp;  /* save ptr to prev entry */
2491                                 privp = privp->next; /* skip to next entry */
2492                         }
2493                 }
2494 
2495                 mutex_exit(&sf->sf_mutex);
2496 
2497                 /*
2498                  * foreach cmd in our list free the ELS packet associated
2499                  * with it
2500                  */
2501                 privp = head;
2502                 while (privp != NULL) {
2503                         fpkt = privp->fpkt;
2504                         privp = privp->next;
2505                         sf_els_free(fpkt);
2506                 }
2507 
2508                 /*
2509                  * scan for commands from each possible target
2510                  */
2511                 for (i = 0; i < sf_max_targets; i++) {
2512                         target = sf->sf_targets[i];
2513                         while (target != NULL) {
2514                                 /*
2515                                  * scan all active commands for this target,
2516                                  * looking for commands that have been issued,
2517                                  * are in transport, and are not yet complete
2518                                  * (so we can terminate them because of the
2519                                  * reset)
2520                                  */
2521                                 mutex_enter(&target->sft_pkt_mutex);
2522                                 cmd = target->sft_pkt_head;
2523                                 while (cmd != (struct sf_pkt *)&target->
2524                                     sft_pkt_head) {
2525                                         fpkt = cmd->cmd_fp_pkt;
2526                                         mutex_enter(&cmd->cmd_abort_mutex);
2527                                         if ((cmd->cmd_state ==
2528                                             SF_STATE_ISSUED) &&
2529                                             (fpkt->fcal_cmd_state &
2530                                             FCAL_CMD_IN_TRANSPORT) &&
2531                                             (!(fpkt->fcal_cmd_state &
2532                                             FCAL_CMD_COMPLETE))) {
2533                                                 /* a command to be reset */
2534                                                 pkt = cmd->cmd_pkt;
2535                                                 pkt->pkt_reason = CMD_RESET;
2536                                                 pkt->pkt_statistics |=
2537                                                     STAT_BUS_RESET;
2538                                                 cmd->cmd_state = SF_STATE_IDLE;
2539                                                 mutex_exit(&cmd->
2540                                                     cmd_abort_mutex);
2541                                                 mutex_exit(&target->
2542                                                     sft_pkt_mutex);
2543                                                 if (pkt->pkt_comp != NULL) {
2544                                                         (*pkt->pkt_comp)(pkt);
2545                                                 }
2546                                                 mutex_enter(&target->
2547                                                     sft_pkt_mutex);
2548                                                 cmd = target->sft_pkt_head;
2549                                         } else {
2550                                                 mutex_exit(&cmd->
2551                                                     cmd_abort_mutex);
2552                                                 /* get next command */
2553                                                 cmd = cmd->cmd_forw;
2554                                         }
2555                                 }
2556                                 mutex_exit(&target->sft_pkt_mutex);
2557                                 target = target->sft_next_lun;
2558                         }
2559                 }
2560 
2561                 /*
2562                  * get packet queue for this target, resetting all remaining
2563                  * commands
2564                  */
2565                 mutex_enter(&sf->sf_mutex);
2566                 cmd = sf->sf_pkt_head;
2567                 sf->sf_pkt_head = NULL;
2568                 mutex_exit(&sf->sf_mutex);
2569 
2570                 while (cmd != NULL) {
2571                         pkt = cmd->cmd_pkt;
2572                         cmd = cmd->cmd_next;
2573                         pkt->pkt_reason = CMD_RESET;
2574                         pkt->pkt_statistics |= STAT_BUS_RESET;
2575                         if (pkt->pkt_comp != NULL) {
2576                                 (*pkt->pkt_comp)(pkt);
2577                         }
2578                 }
2579                 break;
2580         }
2581 
2582         default:
2583                 break;
2584         }
2585 }
2586 
2587 
2588 /*
2589  * called to send a PLOGI (N_port login) ELS request to a destination ID,
2590  * returning TRUE upon success, else returning FALSE
2591  */
2592 static int
2593 sf_login(struct sf *sf, uchar_t els_code, uchar_t dest_id, uint_t arg1,
2594     int lip_cnt)
2595 {
2596         struct la_els_logi      *logi;
2597         struct  sf_els_hdr      *privp;
2598 
2599 
2600         if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr),
2601             sizeof (union sf_els_cmd), sizeof (union sf_els_rsp),
2602             (caddr_t *)&privp, (caddr_t *)&logi) == NULL) {
2603                 sf_log(sf, CE_WARN, "Cannot allocate PLOGI for target %x "
2604                     "due to DVMA shortage.\n", sf_alpa_to_switch[dest_id]);
2605                 return (FALSE);
2606         }
2607 
2608         privp->lip_cnt = lip_cnt;
2609         if (els_code == LA_ELS_PLOGI) {
2610                 bcopy((caddr_t)sf->sf_sochandle->fcal_loginparms,
2611                     (caddr_t)&logi->common_service, sizeof (struct la_els_logi)
2612                     - 4);
2613                 bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
2614                     (caddr_t)&logi->nport_ww_name, sizeof (la_wwn_t));
2615                 bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
2616                     (caddr_t)&logi->node_ww_name, sizeof (la_wwn_t));
2617                 bzero((caddr_t)&logi->reserved, 16);
2618         } else if (els_code == LA_ELS_LOGO) {
2619                 bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
2620                     (caddr_t)&(((struct la_els_logo *)logi)->nport_ww_name), 8);
2621                 ((struct la_els_logo    *)logi)->reserved = 0;
2622                 ((struct la_els_logo    *)logi)->nport_id[0] = 0;
2623                 ((struct la_els_logo    *)logi)->nport_id[1] = 0;
2624                 ((struct la_els_logo    *)logi)->nport_id[2] = arg1;
2625         }
2626 
2627         privp->els_code = els_code;
2628         logi->ls_code = els_code;
2629         logi->mbz[0] = 0;
2630         logi->mbz[1] = 0;
2631         logi->mbz[2] = 0;
2632 
2633         privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2634         return (sf_els_transport(sf, privp));
2635 }
2636 
2637 
2638 /*
2639  * send an ELS IU via the transport,
2640  * returning TRUE upon success, else returning FALSE
2641  */
2642 static int
2643 sf_els_transport(struct sf *sf, struct sf_els_hdr *privp)
2644 {
2645         struct fcal_packet *fpkt = privp->fpkt;
2646 
2647 
2648         (void) ddi_dma_sync(privp->cmd_dma_handle, (off_t)0, (size_t)0,
2649             DDI_DMA_SYNC_FORDEV);
2650         privp->prev = NULL;
2651         mutex_enter(&sf->sf_mutex);
2652         privp->next = sf->sf_els_list;
2653         if (sf->sf_els_list != NULL) {
2654                 sf->sf_els_list->prev = privp;
2655         }
2656         sf->sf_els_list = privp;
2657         mutex_exit(&sf->sf_mutex);
2658 
2659         /* call the transport to send a packet */
2660         if (soc_transport(sf->sf_sochandle, fpkt, FCAL_NOSLEEP,
2661             CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
2662                 mutex_enter(&sf->sf_mutex);
2663                 if (privp->prev != NULL) {
2664                         privp->prev->next = privp->next;
2665                 }
2666                 if (privp->next != NULL) {
2667                         privp->next->prev = privp->prev;
2668                 }
2669                 if (sf->sf_els_list == privp) {
2670                         sf->sf_els_list = privp->next;
2671                 }
2672                 mutex_exit(&sf->sf_mutex);
2673                 sf_els_free(fpkt);
2674                 return (FALSE);                 /* failure */
2675         }
2676         return (TRUE);                          /* success */
2677 }
2678 
2679 
2680 /*
2681  * called as the pkt_comp routine for ELS FC packets
2682  */
2683 static void
2684 sf_els_callback(struct fcal_packet *fpkt)
2685 {
2686         struct sf_els_hdr *privp = fpkt->fcal_pkt_private;
2687         struct sf *sf = privp->sf;
2688         struct sf *tsf;
2689         int tgt_id;
2690         struct la_els_logi *ptr = (struct la_els_logi *)privp->rsp;
2691         struct la_els_adisc *adisc = (struct la_els_adisc *)ptr;
2692         struct  sf_target *target;
2693         short   ncmds;
2694         short   free_pkt = TRUE;
2695 
2696 
2697         /*
2698          * we've received an ELS callback, i.e. an ELS packet has arrived
2699          */
2700 
2701         /* take the current packet off of the queue */
2702         mutex_enter(&sf->sf_mutex);
2703         if (privp->timeout == SF_INVALID_TIMEOUT) {
2704                 mutex_exit(&sf->sf_mutex);
2705                 return;
2706         }
2707         if (privp->prev != NULL) {
2708                 privp->prev->next = privp->next;
2709         }
2710         if (privp->next != NULL) {
2711                 privp->next->prev = privp->prev;
2712         }
2713         if (sf->sf_els_list == privp) {
2714                 sf->sf_els_list = privp->next;
2715         }
2716         privp->prev = privp->next = NULL;
2717         mutex_exit(&sf->sf_mutex);
2718 
2719         /* get # pkts in this callback */
2720         ncmds = fpkt->fcal_ncmds;
2721         ASSERT(ncmds >= 0);
2722         mutex_enter(&sf->sf_cmd_mutex);
2723         sf->sf_ncmds = ncmds;
2724         mutex_exit(&sf->sf_cmd_mutex);
2725 
2726         /* sync idea of memory */
2727         (void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0, (size_t)0,
2728             DDI_DMA_SYNC_FORKERNEL);
2729 
2730         /* was this an OK ACC msg ?? */
2731         if ((fpkt->fcal_pkt_status == FCAL_STATUS_OK) &&
2732             (ptr->ls_code == LA_ELS_ACC)) {
2733 
2734                 /*
2735                  * this was an OK ACC pkt
2736                  */
2737 
2738                 switch (privp->els_code) {
2739                 case LA_ELS_PLOGI:
2740                         /*
2741                          * was able to to an N_port login
2742                          */
2743                         SF_DEBUG(2, (sf, CE_CONT,
2744                             "!PLOGI to al_pa %x succeeded, wwn %x%x\n",
2745                             privp->dest_nport_id,
2746                             *((int *)&ptr->nport_ww_name.raw_wwn[0]),
2747                             *((int *)&ptr->nport_ww_name.raw_wwn[4])));
2748                         /* try to do a process login */
2749                         if (!sf_do_prli(sf, privp, ptr)) {
2750                                 free_pkt = FALSE;
2751                                 goto fail;      /* PRLI failed */
2752                         }
2753                         break;
2754                 case LA_ELS_PRLI:
2755                         /*
2756                          * was able to do a process login
2757                          */
2758                         SF_DEBUG(2, (sf, CE_CONT,
2759                             "!PRLI to al_pa %x succeeded\n",
2760                             privp->dest_nport_id));
2761                         /* try to do address discovery */
2762                         if (sf_do_adisc(sf, privp) != 1) {
2763                                 free_pkt = FALSE;
2764                                 goto fail;      /* ADISC failed */
2765                         }
2766                         break;
2767                 case LA_ELS_ADISC:
2768                         /*
2769                          * found a target via ADISC
2770                          */
2771 
2772                         SF_DEBUG(2, (sf, CE_CONT,
2773                             "!ADISC to al_pa %x succeeded\n",
2774                             privp->dest_nport_id));
2775 
2776                         /* create the target info */
2777                         if ((target = sf_create_target(sf, privp,
2778                             sf_alpa_to_switch[(uchar_t)adisc->hard_address],
2779                             (int64_t)0))
2780                             == NULL) {
2781                                 goto fail;      /* can't create target */
2782                         }
2783 
2784                         /*
2785                          * ensure address discovered matches what we thought
2786                          * it would be
2787                          */
2788                         if ((uchar_t)adisc->hard_address !=
2789                             privp->dest_nport_id) {
2790                                 sf_log(sf, CE_WARN,
2791                                     "target 0x%x, AL-PA 0x%x and "
2792                                     "hard address 0x%x don't match\n",
2793                                     sf_alpa_to_switch[
2794                                     (uchar_t)privp->dest_nport_id],
2795                                     privp->dest_nport_id,
2796                                     (uchar_t)adisc->hard_address);
2797                                 mutex_enter(&sf->sf_mutex);
2798                                 sf_offline_target(sf, target);
2799                                 mutex_exit(&sf->sf_mutex);
2800                                 goto fail;      /* addr doesn't match */
2801                         }
2802                         /*
2803                          * get inquiry data from the target
2804                          */
2805                         if (!sf_do_reportlun(sf, privp, target)) {
2806                                 mutex_enter(&sf->sf_mutex);
2807                                 sf_offline_target(sf, target);
2808                                 mutex_exit(&sf->sf_mutex);
2809                                 free_pkt = FALSE;
2810                                 goto fail;      /* inquiry failed */
2811                         }
2812                         break;
2813                 default:
2814                         SF_DEBUG(2, (sf, CE_CONT,
2815                             "!ELS %x to al_pa %x succeeded\n",
2816                             privp->els_code, privp->dest_nport_id));
2817                         sf_els_free(fpkt);
2818                         break;
2819                 }
2820 
2821         } else {
2822 
2823                 /*
2824                  * oh oh -- this was not an OK ACC packet
2825                  */
2826 
2827                 /* get target ID from dest loop address */
2828                 tgt_id = sf_alpa_to_switch[(uchar_t)privp->dest_nport_id];
2829 
2830                 /* keep track of failures */
2831                 sf->sf_stats.tstats[tgt_id].els_failures++;
2832                 if (++(privp->retries) < sf_els_retries &&
2833                     fpkt->fcal_pkt_status != FCAL_STATUS_OPEN_FAIL) {
2834                         if (fpkt->fcal_pkt_status ==
2835                             FCAL_STATUS_MAX_XCHG_EXCEEDED)  {
2836                                 tsf = sf->sf_sibling;
2837                                 if (tsf != NULL) {
2838                                         mutex_enter(&tsf->sf_cmd_mutex);
2839                                         tsf->sf_flag = 1;
2840                                         tsf->sf_throttle = SF_DECR_DELTA;
2841                                         mutex_exit(&tsf->sf_cmd_mutex);
2842                                 }
2843                         }
2844                         privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2845                         privp->prev = NULL;
2846 
2847                         mutex_enter(&sf->sf_mutex);
2848 
2849                         if (privp->lip_cnt == sf->sf_lip_cnt) {
2850                                 SF_DEBUG(1, (sf, CE_WARN,
2851                                     "!ELS %x to al_pa %x failed, retrying",
2852                                     privp->els_code, privp->dest_nport_id));
2853                                 privp->next = sf->sf_els_list;
2854                                 if (sf->sf_els_list != NULL) {
2855                                         sf->sf_els_list->prev = privp;
2856                                 }
2857 
2858                                 sf->sf_els_list = privp;
2859 
2860                                 mutex_exit(&sf->sf_mutex);
2861                                 /* device busy?  wait a bit ... */
2862                                 if (fpkt->fcal_pkt_status ==
2863                                     FCAL_STATUS_MAX_XCHG_EXCEEDED)  {
2864                                         privp->delayed_retry = 1;
2865                                         return;
2866                                 }
2867                                 /* call the transport to send a pkt */
2868                                 if (soc_transport(sf->sf_sochandle, fpkt,
2869                                     FCAL_NOSLEEP, CQ_REQUEST_1) !=
2870                                     FCAL_TRANSPORT_SUCCESS) {
2871                                         mutex_enter(&sf->sf_mutex);
2872                                         if (privp->prev != NULL) {
2873                                                 privp->prev->next =
2874                                                     privp->next;
2875                                         }
2876                                         if (privp->next != NULL) {
2877                                                 privp->next->prev =
2878                                                     privp->prev;
2879                                         }
2880                                         if (sf->sf_els_list == privp) {
2881                                                 sf->sf_els_list = privp->next;
2882                                         }
2883                                         mutex_exit(&sf->sf_mutex);
2884                                         goto fail;
2885                                 } else
2886                                         return;
2887                         } else {
2888                                 mutex_exit(&sf->sf_mutex);
2889                                 goto fail;
2890                         }
2891                 } else {
2892 #ifdef  DEBUG
2893                         if (fpkt->fcal_pkt_status != 0x36 || sfdebug > 4) {
2894                         SF_DEBUG(2, (sf, CE_NOTE, "ELS %x to al_pa %x failed",
2895                             privp->els_code, privp->dest_nport_id));
2896                         if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
2897                                 SF_DEBUG(2, (sf, CE_NOTE,
2898                                     "els reply code = %x", ptr->ls_code));
2899                                 if (ptr->ls_code == LA_ELS_RJT)
2900                                         SF_DEBUG(1, (sf, CE_CONT,
2901                                             "LS_RJT reason = %x\n",
2902                                             *(((uint_t *)ptr) + 1)));
2903                         } else
2904                                 SF_DEBUG(2, (sf, CE_NOTE,
2905                                     "fc packet status = %x",
2906                                     fpkt->fcal_pkt_status));
2907                         }
2908 #endif
2909                         goto fail;
2910                 }
2911         }
2912         return;                                 /* success */
2913 fail:
2914         mutex_enter(&sf->sf_mutex);
2915         if (sf->sf_lip_cnt == privp->lip_cnt) {
2916                 sf->sf_device_count--;
2917                 ASSERT(sf->sf_device_count >= 0);
2918                 if (sf->sf_device_count == 0) {
2919                         sf_finish_init(sf, privp->lip_cnt);
2920                 }
2921         }
2922         mutex_exit(&sf->sf_mutex);
2923         if (free_pkt) {
2924                 sf_els_free(fpkt);
2925         }
2926 }
2927 
2928 
2929 /*
2930  * send a PRLI (process login) ELS IU via the transport,
2931  * returning TRUE upon success, else returning FALSE
2932  */
2933 static int
2934 sf_do_prli(struct sf *sf, struct sf_els_hdr *privp, struct la_els_logi *ptr)
2935 {
2936         struct la_els_prli      *prli = (struct la_els_prli *)privp->cmd;
2937         struct fcp_prli         *fprli;
2938         struct  fcal_packet     *fpkt = privp->fpkt;
2939 
2940 
2941         fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
2942             sizeof (struct la_els_prli);
2943         privp->els_code = LA_ELS_PRLI;
2944         fprli = (struct fcp_prli *)prli->service_params;
2945         prli->ls_code = LA_ELS_PRLI;
2946         prli->page_length = 0x10;
2947         prli->payload_length = sizeof (struct la_els_prli);
2948         fprli->type = 0x08;                  /* no define here? */
2949         fprli->resvd1 = 0;
2950         fprli->orig_process_assoc_valid = 0;
2951         fprli->resp_process_assoc_valid = 0;
2952         fprli->establish_image_pair = 1;
2953         fprli->resvd2 = 0;
2954         fprli->resvd3 = 0;
2955         fprli->data_overlay_allowed = 0;
2956         fprli->initiator_fn = 1;
2957         fprli->target_fn = 0;
2958         fprli->cmd_data_mixed = 0;
2959         fprli->data_resp_mixed = 0;
2960         fprli->read_xfer_rdy_disabled = 1;
2961         fprli->write_xfer_rdy_disabled = 0;
2962 
2963         bcopy((caddr_t)&ptr->nport_ww_name, (caddr_t)&privp->port_wwn,
2964             sizeof (privp->port_wwn));
2965         bcopy((caddr_t)&ptr->node_ww_name, (caddr_t)&privp->node_wwn,
2966             sizeof (privp->node_wwn));
2967 
2968         privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2969         return (sf_els_transport(sf, privp));
2970 }
2971 
2972 
2973 /*
2974  * send an ADISC (address discovery) ELS IU via the transport,
2975  * returning TRUE upon success, else returning FALSE
2976  */
2977 static int
2978 sf_do_adisc(struct sf *sf, struct sf_els_hdr *privp)
2979 {
2980         struct la_els_adisc     *adisc = (struct la_els_adisc *)privp->cmd;
2981         struct  fcal_packet     *fpkt = privp->fpkt;
2982 
2983         privp->els_code = LA_ELS_ADISC;
2984         adisc->ls_code = LA_ELS_ADISC;
2985         adisc->mbz[0] = 0;
2986         adisc->mbz[1] = 0;
2987         adisc->mbz[2] = 0;
2988         adisc->hard_address = 0; /* ??? */
2989         fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
2990             sizeof (struct la_els_adisc);
2991         bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
2992             (caddr_t)&adisc->port_wwn, sizeof (adisc->port_wwn));
2993         bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
2994             (caddr_t)&adisc->node_wwn, sizeof (adisc->node_wwn));
2995         adisc->nport_id = sf->sf_al_pa;
2996 
2997         privp->timeout = sf_watchdog_time + SF_ELS_TIMEOUT;
2998         return (sf_els_transport(sf, privp));
2999 }
3000 
3001 
3002 static struct fcal_packet *
3003 sf_els_alloc(struct sf *sf, uchar_t dest_id, int priv_size, int cmd_size,
3004     int rsp_size, caddr_t *rprivp, caddr_t *cmd_buf)
3005 {
3006         struct  fcal_packet     *fpkt;
3007         ddi_dma_cookie_t        pcookie;
3008         ddi_dma_cookie_t        rcookie;
3009         struct  sf_els_hdr      *privp;
3010         ddi_dma_handle_t        cmd_dma_handle = NULL;
3011         ddi_dma_handle_t        rsp_dma_handle = NULL;
3012         ddi_acc_handle_t        cmd_acc_handle = NULL;
3013         ddi_acc_handle_t        rsp_acc_handle = NULL;
3014         size_t                  real_size;
3015         uint_t                  ccount;
3016         fc_frame_header_t       *hp;
3017         int                     cmd_bound = FALSE, rsp_bound = FALSE;
3018         caddr_t                 cmd = NULL;
3019         caddr_t                 rsp = NULL;
3020 
3021         if ((fpkt = (struct fcal_packet *)kmem_zalloc(
3022             sizeof (struct fcal_packet), KM_NOSLEEP)) == NULL) {
3023                 SF_DEBUG(1, (sf, CE_WARN,
3024                         "Could not allocate fcal_packet for ELS\n"));
3025                 return (NULL);
3026         }
3027 
3028         if ((privp = (struct sf_els_hdr *)kmem_zalloc(priv_size,
3029             KM_NOSLEEP)) == NULL) {
3030                 SF_DEBUG(1, (sf, CE_WARN,
3031                     "Could not allocate sf_els_hdr for ELS\n"));
3032                 goto fail;
3033         }
3034 
3035         privp->size = priv_size;
3036         fpkt->fcal_pkt_private = (caddr_t)privp;
3037 
3038         if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3039             DDI_DMA_DONTWAIT, NULL, &cmd_dma_handle) != DDI_SUCCESS) {
3040                 SF_DEBUG(1, (sf, CE_WARN,
3041                     "Could not allocate DMA handle for ELS\n"));
3042                 goto fail;
3043         }
3044 
3045         if (ddi_dma_mem_alloc(cmd_dma_handle, cmd_size,
3046             sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3047             DDI_DMA_DONTWAIT, NULL, &cmd,
3048             &real_size, &cmd_acc_handle) != DDI_SUCCESS) {
3049                 SF_DEBUG(1, (sf, CE_WARN,
3050                     "Could not allocate DMA memory for ELS\n"));
3051                 goto fail;
3052         }
3053 
3054         if (real_size < cmd_size) {
3055                 SF_DEBUG(1, (sf, CE_WARN,
3056                     "DMA memory too small for ELS\n"));
3057                 goto fail;
3058         }
3059 
3060         if (ddi_dma_addr_bind_handle(cmd_dma_handle, NULL,
3061             cmd, real_size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
3062             DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3063                 SF_DEBUG(1, (sf, CE_WARN,
3064                     "Could not bind DMA memory for ELS\n"));
3065                 goto fail;
3066         }
3067         cmd_bound = TRUE;
3068 
3069         if (ccount != 1) {
3070                 SF_DEBUG(1, (sf, CE_WARN,
3071                     "Wrong cookie count for ELS\n"));
3072                 goto fail;
3073         }
3074 
3075         if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3076             DDI_DMA_DONTWAIT, NULL, &rsp_dma_handle) != DDI_SUCCESS) {
3077                 SF_DEBUG(1, (sf, CE_WARN,
3078                     "Could not allocate DMA handle for ELS rsp\n"));
3079                 goto fail;
3080         }
3081         if (ddi_dma_mem_alloc(rsp_dma_handle, rsp_size,
3082             sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3083             DDI_DMA_DONTWAIT, NULL, &rsp,
3084             &real_size, &rsp_acc_handle) != DDI_SUCCESS) {
3085                 SF_DEBUG(1, (sf, CE_WARN,
3086                     "Could not allocate DMA memory for ELS rsp\n"));
3087                 goto fail;
3088         }
3089 
3090         if (real_size < rsp_size) {
3091                 SF_DEBUG(1, (sf, CE_WARN,
3092                     "DMA memory too small for ELS rsp\n"));
3093                 goto fail;
3094         }
3095 
3096         if (ddi_dma_addr_bind_handle(rsp_dma_handle, NULL,
3097             rsp, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT,
3098             DDI_DMA_DONTWAIT, NULL, &rcookie, &ccount) != DDI_DMA_MAPPED) {
3099                 SF_DEBUG(1, (sf, CE_WARN,
3100                     "Could not bind DMA memory for ELS rsp\n"));
3101                 goto fail;
3102         }
3103         rsp_bound = TRUE;
3104 
3105         if (ccount != 1) {
3106                 SF_DEBUG(1, (sf, CE_WARN,
3107                     "Wrong cookie count for ELS rsp\n"));
3108                 goto fail;
3109         }
3110 
3111         privp->cmd = cmd;
3112         privp->sf = sf;
3113         privp->cmd_dma_handle = cmd_dma_handle;
3114         privp->cmd_acc_handle = cmd_acc_handle;
3115         privp->rsp = rsp;
3116         privp->rsp_dma_handle = rsp_dma_handle;
3117         privp->rsp_acc_handle = rsp_acc_handle;
3118         privp->dest_nport_id = dest_id;
3119         privp->fpkt = fpkt;
3120 
3121         fpkt->fcal_pkt_cookie = sf->sf_socp;
3122         fpkt->fcal_pkt_comp = sf_els_callback;
3123         fpkt->fcal_magic = FCALP_MAGIC;
3124         fpkt->fcal_pkt_flags = 0;
3125         fpkt->fcal_socal_request.sr_soc_hdr.sh_flags =
3126             (ushort_t)(SOC_FC_HEADER | sf->sf_sochandle->fcal_portno);
3127         fpkt->fcal_socal_request.sr_soc_hdr.sh_class = 3;
3128         fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 2;
3129         fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = cmd_size;
3130         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_count = 1;
3131         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_flags = 0;
3132         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_seqno = 0;
3133         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_SIMPLE;
3134         fpkt->fcal_socal_request.sr_dataseg[0].fc_base = (uint32_t)
3135             pcookie.dmac_address;
3136         fpkt->fcal_socal_request.sr_dataseg[0].fc_count = cmd_size;
3137         fpkt->fcal_socal_request.sr_dataseg[1].fc_base = (uint32_t)
3138             rcookie.dmac_address;
3139         fpkt->fcal_socal_request.sr_dataseg[1].fc_count = rsp_size;
3140 
3141         /* Fill in the Fabric Channel Header */
3142         hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3143         hp->r_ctl = R_CTL_ELS_REQ;
3144         hp->d_id = dest_id;
3145         hp->s_id = sf->sf_al_pa;
3146         hp->type = TYPE_EXTENDED_LS;
3147         hp->reserved1 = 0;
3148         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3149         hp->seq_id = 0;
3150         hp->df_ctl  = 0;
3151         hp->seq_cnt = 0;
3152         hp->ox_id = 0xffff;
3153         hp->rx_id = 0xffff;
3154         hp->ro = 0;
3155 
3156         *rprivp = (caddr_t)privp;
3157         *cmd_buf = cmd;
3158         return (fpkt);
3159 
3160 fail:
3161         if (cmd_dma_handle != NULL) {
3162                 if (cmd_bound) {
3163                         (void) ddi_dma_unbind_handle(cmd_dma_handle);
3164                 }
3165                 ddi_dma_free_handle(&cmd_dma_handle);
3166                 privp->cmd_dma_handle = NULL;
3167         }
3168         if (rsp_dma_handle != NULL) {
3169                 if (rsp_bound) {
3170                         (void) ddi_dma_unbind_handle(rsp_dma_handle);
3171                 }
3172                 ddi_dma_free_handle(&rsp_dma_handle);
3173                 privp->rsp_dma_handle = NULL;
3174         }
3175         sf_els_free(fpkt);
3176         return (NULL);
3177 }
3178 
3179 
3180 static void
3181 sf_els_free(struct fcal_packet *fpkt)
3182 {
3183         struct  sf_els_hdr      *privp = fpkt->fcal_pkt_private;
3184 
3185         if (privp != NULL) {
3186                 if (privp->cmd_dma_handle != NULL) {
3187                         (void) ddi_dma_unbind_handle(privp->cmd_dma_handle);
3188                         ddi_dma_free_handle(&privp->cmd_dma_handle);
3189                 }
3190                 if (privp->cmd != NULL) {
3191                         ddi_dma_mem_free(&privp->cmd_acc_handle);
3192                 }
3193 
3194                 if (privp->rsp_dma_handle != NULL) {
3195                         (void) ddi_dma_unbind_handle(privp->rsp_dma_handle);
3196                         ddi_dma_free_handle(&privp->rsp_dma_handle);
3197                 }
3198 
3199                 if (privp->rsp != NULL) {
3200                         ddi_dma_mem_free(&privp->rsp_acc_handle);
3201                 }
3202                 if (privp->data_dma_handle) {
3203                         (void) ddi_dma_unbind_handle(privp->data_dma_handle);
3204                         ddi_dma_free_handle(&privp->data_dma_handle);
3205                 }
3206                 if (privp->data_buf) {
3207                         ddi_dma_mem_free(&privp->data_acc_handle);
3208                 }
3209                 kmem_free(privp, privp->size);
3210         }
3211         kmem_free(fpkt, sizeof (struct fcal_packet));
3212 }
3213 
3214 
3215 static struct sf_target *
3216 sf_create_target(struct sf *sf, struct sf_els_hdr *privp, int tnum, int64_t lun)
3217 {
3218         struct sf_target *target, *ntarget, *otarget, *ptarget;
3219         int hash;
3220 #ifdef RAID_LUNS
3221         int64_t orig_lun = lun;
3222 
3223         /* XXXX Work around SCSA limitations. */
3224         lun = *((short *)&lun);
3225 #endif
3226         ntarget = kmem_zalloc(sizeof (struct sf_target), KM_NOSLEEP);
3227         mutex_enter(&sf->sf_mutex);
3228         if (sf->sf_lip_cnt != privp->lip_cnt) {
3229                 mutex_exit(&sf->sf_mutex);
3230                 if (ntarget != NULL)
3231                         kmem_free(ntarget, sizeof (struct sf_target));
3232                 return (NULL);
3233         }
3234 
3235         target = sf_lookup_target(sf, privp->port_wwn, lun);
3236         if (lun != 0) {
3237                 /*
3238                  * Since LUNs != 0 are queued up after LUN == 0, find LUN == 0
3239                  * and enqueue the new LUN.
3240                  */
3241                 if ((ptarget = sf_lookup_target(sf, privp->port_wwn,
3242                     (int64_t)0)) ==     NULL) {
3243                         /*
3244                          * Yeep -- no LUN 0?
3245                          */
3246                         mutex_exit(&sf->sf_mutex);
3247                         sf_log(sf, CE_WARN, "target 0x%x "
3248                             "lun %" PRIx64 ": No LUN 0\n", tnum, lun);
3249                         if (ntarget != NULL)
3250                                 kmem_free(ntarget, sizeof (struct sf_target));
3251                         return (NULL);
3252                 }
3253                 mutex_enter(&ptarget->sft_mutex);
3254                 if (target != NULL && ptarget->sft_lip_cnt == sf->sf_lip_cnt &&
3255                     ptarget->sft_state&SF_TARGET_OFFLINE) {
3256                         /* LUN 0 already finished, duplicate its state */
3257                         mutex_exit(&ptarget->sft_mutex);
3258                         sf_offline_target(sf, target);
3259                         mutex_exit(&sf->sf_mutex);
3260                         if (ntarget != NULL)
3261                                 kmem_free(ntarget, sizeof (struct sf_target));
3262                         return (target);
3263                 } else if (target != NULL) {
3264                         /*
3265                          * LUN 0 online or not examined yet.
3266                          * Try to bring the LUN back online
3267                          */
3268                         mutex_exit(&ptarget->sft_mutex);
3269                         mutex_enter(&target->sft_mutex);
3270                         target->sft_lip_cnt = privp->lip_cnt;
3271                         target->sft_state |= SF_TARGET_BUSY;
3272                         target->sft_state &= ~(SF_TARGET_OFFLINE|
3273                             SF_TARGET_MARK);
3274                         target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3275                         target->sft_hard_address = sf_switch_to_alpa[tnum];
3276                         mutex_exit(&target->sft_mutex);
3277                         mutex_exit(&sf->sf_mutex);
3278                         if (ntarget != NULL)
3279                                 kmem_free(ntarget, sizeof (struct sf_target));
3280                         return (target);
3281                 }
3282                 mutex_exit(&ptarget->sft_mutex);
3283                 if (ntarget == NULL) {
3284                         mutex_exit(&sf->sf_mutex);
3285                         return (NULL);
3286                 }
3287                 /* Initialize new target structure */
3288                 bcopy((caddr_t)&privp->node_wwn,
3289                     (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn));
3290                 bcopy((caddr_t)&privp->port_wwn,
3291                     (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn));
3292                 ntarget->sft_lun.l = lun;
3293 #ifdef RAID_LUNS
3294                 ntarget->sft_lun.l = orig_lun;
3295                 ntarget->sft_raid_lun = (uint_t)lun;
3296 #endif
3297                 mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL);
3298                 mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
3299                 /* Don't let anyone use this till we finishup init. */
3300                 mutex_enter(&ntarget->sft_mutex);
3301                 mutex_enter(&ntarget->sft_pkt_mutex);
3302 
3303                 hash = SF_HASH(privp->port_wwn, lun);
3304                 ntarget->sft_next = sf->sf_wwn_lists[hash];
3305                 sf->sf_wwn_lists[hash] = ntarget;
3306 
3307                 ntarget->sft_lip_cnt = privp->lip_cnt;
3308                 ntarget->sft_al_pa = (uchar_t)privp->dest_nport_id;
3309                 ntarget->sft_hard_address = sf_switch_to_alpa[tnum];
3310                 ntarget->sft_device_type = DTYPE_UNKNOWN;
3311                 ntarget->sft_state = SF_TARGET_BUSY;
3312                 ntarget->sft_pkt_head = (struct sf_pkt *)&ntarget->
3313                     sft_pkt_head;
3314                 ntarget->sft_pkt_tail = (struct sf_pkt *)&ntarget->
3315                     sft_pkt_head;
3316 
3317                 mutex_enter(&ptarget->sft_mutex);
3318                 /* Traverse the list looking for this target */
3319                 for (target = ptarget; target->sft_next_lun;
3320                     target = target->sft_next_lun) {
3321                         otarget = target->sft_next_lun;
3322                 }
3323                 ntarget->sft_next_lun = target->sft_next_lun;
3324                 target->sft_next_lun = ntarget;
3325                 mutex_exit(&ptarget->sft_mutex);
3326                 mutex_exit(&ntarget->sft_pkt_mutex);
3327                 mutex_exit(&ntarget->sft_mutex);
3328                 mutex_exit(&sf->sf_mutex);
3329                 return (ntarget);
3330 
3331         }
3332         if (target != NULL && target->sft_lip_cnt == sf->sf_lip_cnt) {
3333                 /* It's been touched this LIP -- duplicate WWNs */
3334                 sf_offline_target(sf, target); /* And all the baby targets */
3335                 mutex_exit(&sf->sf_mutex);
3336                 sf_log(sf, CE_WARN, "target 0x%x, duplicate port wwns\n",
3337                     tnum);
3338                 if (ntarget != NULL) {
3339                         kmem_free(ntarget, sizeof (struct sf_target));
3340                 }
3341                 return (NULL);
3342         }
3343 
3344         if ((otarget = sf->sf_targets[tnum]) != NULL) {
3345                 /* Someone else is in our slot */
3346                 mutex_enter(&otarget->sft_mutex);
3347                 if (otarget->sft_lip_cnt == sf->sf_lip_cnt) {
3348                         mutex_exit(&otarget->sft_mutex);
3349                         sf_offline_target(sf, otarget);
3350                         if (target != NULL)
3351                                 sf_offline_target(sf, target);
3352                         mutex_exit(&sf->sf_mutex);
3353                         sf_log(sf, CE_WARN,
3354                             "target 0x%x, duplicate switch settings\n", tnum);
3355                         if (ntarget != NULL)
3356                                 kmem_free(ntarget, sizeof (struct sf_target));
3357                         return (NULL);
3358                 }
3359                 mutex_exit(&otarget->sft_mutex);
3360                 if (bcmp((caddr_t)&privp->port_wwn, (caddr_t)&otarget->
3361                     sft_port_wwn, sizeof (privp->port_wwn))) {
3362                         sf_offline_target(sf, otarget);
3363                         mutex_exit(&sf->sf_mutex);
3364                         sf_log(sf, CE_WARN, "wwn changed on target 0x%x\n",
3365                             tnum);
3366                         bzero((caddr_t)&sf->sf_stats.tstats[tnum],
3367                             sizeof (struct sf_target_stats));
3368                         mutex_enter(&sf->sf_mutex);
3369                 }
3370         }
3371 
3372         sf->sf_targets[tnum] = target;
3373         if ((target = sf->sf_targets[tnum]) == NULL) {
3374                 if (ntarget == NULL) {
3375                         mutex_exit(&sf->sf_mutex);
3376                         return (NULL);
3377                 }
3378                 bcopy((caddr_t)&privp->node_wwn,
3379                     (caddr_t)&ntarget->sft_node_wwn, sizeof (privp->node_wwn));
3380                 bcopy((caddr_t)&privp->port_wwn,
3381                     (caddr_t)&ntarget->sft_port_wwn, sizeof (privp->port_wwn));
3382                 ntarget->sft_lun.l = lun;
3383 #ifdef RAID_LUNS
3384                 ntarget->sft_lun.l = orig_lun;
3385                 ntarget->sft_raid_lun = (uint_t)lun;
3386 #endif
3387                 mutex_init(&ntarget->sft_mutex, NULL, MUTEX_DRIVER, NULL);
3388                 mutex_init(&ntarget->sft_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
3389                 mutex_enter(&ntarget->sft_mutex);
3390                 mutex_enter(&ntarget->sft_pkt_mutex);
3391                 hash = SF_HASH(privp->port_wwn, lun); /* lun 0 */
3392                 ntarget->sft_next = sf->sf_wwn_lists[hash];
3393                 sf->sf_wwn_lists[hash] = ntarget;
3394 
3395                 target = ntarget;
3396                 target->sft_lip_cnt = privp->lip_cnt;
3397                 target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3398                 target->sft_hard_address = sf_switch_to_alpa[tnum];
3399                 target->sft_device_type = DTYPE_UNKNOWN;
3400                 target->sft_state = SF_TARGET_BUSY;
3401                 target->sft_pkt_head = (struct sf_pkt *)&target->
3402                     sft_pkt_head;
3403                 target->sft_pkt_tail = (struct sf_pkt *)&target->
3404                     sft_pkt_head;
3405                 sf->sf_targets[tnum] = target;
3406                 mutex_exit(&ntarget->sft_mutex);
3407                 mutex_exit(&ntarget->sft_pkt_mutex);
3408                 mutex_exit(&sf->sf_mutex);
3409         } else {
3410                 mutex_enter(&target->sft_mutex);
3411                 target->sft_lip_cnt = privp->lip_cnt;
3412                 target->sft_state |= SF_TARGET_BUSY;
3413                 target->sft_state &= ~(SF_TARGET_OFFLINE|SF_TARGET_MARK);
3414                 target->sft_al_pa = (uchar_t)privp->dest_nport_id;
3415                 target->sft_hard_address = sf_switch_to_alpa[tnum];
3416                 mutex_exit(&target->sft_mutex);
3417                 mutex_exit(&sf->sf_mutex);
3418                 if (ntarget != NULL)
3419                         kmem_free(ntarget, sizeof (struct sf_target));
3420         }
3421         return (target);
3422 }
3423 
3424 
3425 /*
3426  * find the target for a given sf instance
3427  */
3428 /* ARGSUSED */
3429 static struct sf_target *
3430 #ifdef RAID_LUNS
3431 sf_lookup_target(struct sf *sf, uchar_t *wwn, int lun)
3432 #else
3433 sf_lookup_target(struct sf *sf, uchar_t *wwn, int64_t lun)
3434 #endif
3435 {
3436         int hash;
3437         struct sf_target *target;
3438 
3439         ASSERT(mutex_owned(&sf->sf_mutex));
3440         hash = SF_HASH(wwn, lun);
3441 
3442         target = sf->sf_wwn_lists[hash];
3443         while (target != NULL) {
3444 
3445 #ifndef RAID_LUNS
3446                 if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn,
3447                     sizeof (target->sft_port_wwn)) == 0 &&
3448                         target->sft_lun.l == lun)
3449                         break;
3450 #else
3451                 if (bcmp((caddr_t)wwn, (caddr_t)&target->sft_port_wwn,
3452                     sizeof (target->sft_port_wwn)) == 0 &&
3453                         target->sft_raid_lun == lun)
3454                         break;
3455 #endif
3456                 target = target->sft_next;
3457         }
3458 
3459         return (target);
3460 }
3461 
3462 
3463 /*
3464  * Send out a REPORT_LUNS command.
3465  */
3466 static int
3467 sf_do_reportlun(struct sf *sf, struct sf_els_hdr *privp,
3468     struct sf_target *target)
3469 {
3470         struct  fcal_packet     *fpkt = privp->fpkt;
3471         ddi_dma_cookie_t        pcookie;
3472         ddi_dma_handle_t        lun_dma_handle = NULL;
3473         ddi_acc_handle_t        lun_acc_handle;
3474         uint_t                  ccount;
3475         size_t                  real_size;
3476         caddr_t                 lun_buf = NULL;
3477         int                     handle_bound = 0;
3478         fc_frame_header_t       *hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3479         struct fcp_cmd          *reportlun = (struct fcp_cmd *)privp->cmd;
3480         char                    *msg = "Transport";
3481 
3482         if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3483             DDI_DMA_DONTWAIT, NULL, &lun_dma_handle) != DDI_SUCCESS) {
3484                 msg = "ddi_dma_alloc_handle()";
3485                 goto fail;
3486         }
3487 
3488         if (ddi_dma_mem_alloc(lun_dma_handle, REPORT_LUNS_SIZE,
3489             sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3490             DDI_DMA_DONTWAIT, NULL, &lun_buf,
3491             &real_size, &lun_acc_handle) != DDI_SUCCESS) {
3492                 msg = "ddi_dma_mem_alloc()";
3493                 goto fail;
3494         }
3495 
3496         if (real_size < REPORT_LUNS_SIZE) {
3497                 msg = "DMA mem < REPORT_LUNS_SIZE";
3498                 goto fail;
3499         }
3500 
3501         if (ddi_dma_addr_bind_handle(lun_dma_handle, NULL,
3502             lun_buf, real_size, DDI_DMA_READ |
3503             DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT,
3504             NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3505                 msg = "ddi_dma_addr_bind_handle()";
3506                 goto fail;
3507         }
3508         handle_bound = 1;
3509 
3510         if (ccount != 1) {
3511                 msg = "ccount != 1";
3512                 goto fail;
3513         }
3514         privp->els_code = 0;
3515         privp->target = target;
3516         privp->data_dma_handle = lun_dma_handle;
3517         privp->data_acc_handle = lun_acc_handle;
3518         privp->data_buf = lun_buf;
3519 
3520         fpkt->fcal_pkt_comp = sf_reportlun_callback;
3521         fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
3522         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ;
3523         fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3524             sizeof (struct fcp_cmd);
3525         fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
3526             (uint32_t)pcookie.dmac_address;
3527         fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size;
3528         fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size;
3529         hp->r_ctl = R_CTL_COMMAND;
3530         hp->type = TYPE_SCSI_FCP;
3531         bzero((caddr_t)reportlun, sizeof (struct fcp_cmd));
3532         ((union scsi_cdb *)reportlun->fcp_cdb)->scc_cmd = SCMD_REPORT_LUNS;
3533         /* Now set the buffer size.  If DDI gave us extra, that's O.K. */
3534         ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count0 =
3535             (real_size&0x0ff);
3536         ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count1 =
3537             (real_size>>8)&0x0ff;
3538         ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count2 =
3539             (real_size>>16)&0x0ff;
3540         ((union scsi_cdb *)reportlun->fcp_cdb)->scc5_count3 =
3541             (real_size>>24)&0x0ff;
3542         reportlun->fcp_cntl.cntl_read_data = 1;
3543         reportlun->fcp_cntl.cntl_write_data = 0;
3544         reportlun->fcp_data_len = pcookie.dmac_size;
3545         reportlun->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
3546 
3547         (void) ddi_dma_sync(lun_dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
3548         /* We know he's there, so this should be fast */
3549         privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3550         if (sf_els_transport(sf, privp) == 1)
3551                 return (1);
3552 
3553 fail:
3554         sf_log(sf, CE_WARN,
3555             "%s failure for REPORTLUN to target 0x%x\n",
3556             msg, sf_alpa_to_switch[privp->dest_nport_id]);
3557         sf_els_free(fpkt);
3558         if (lun_dma_handle != NULL) {
3559                 if (handle_bound)
3560                         (void) ddi_dma_unbind_handle(lun_dma_handle);
3561                 ddi_dma_free_handle(&lun_dma_handle);
3562         }
3563         if (lun_buf != NULL) {
3564                 ddi_dma_mem_free(&lun_acc_handle);
3565         }
3566         return (0);
3567 }
3568 
3569 /*
3570  * Handle the results of a REPORT_LUNS command:
3571  *      Create additional targets if necessary
3572  *      Initiate INQUIRYs on all LUNs.
3573  */
3574 static void
3575 sf_reportlun_callback(struct fcal_packet *fpkt)
3576 {
3577         struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt->
3578             fcal_pkt_private;
3579         struct scsi_report_luns *ptr =
3580             (struct scsi_report_luns *)privp->data_buf;
3581         struct sf *sf = privp->sf;
3582         struct sf_target *target = privp->target;
3583         struct fcp_rsp *rsp = NULL;
3584         int delayed_retry = 0;
3585         int tid = sf_alpa_to_switch[target->sft_hard_address];
3586         int i, free_pkt = 1;
3587         short   ncmds;
3588 
3589         mutex_enter(&sf->sf_mutex);
3590         /* use as temporary state variable */
3591         if (privp->timeout == SF_INVALID_TIMEOUT) {
3592                 mutex_exit(&sf->sf_mutex);
3593                 return;
3594         }
3595         if (privp->prev)
3596                 privp->prev->next = privp->next;
3597         if (privp->next)
3598                 privp->next->prev = privp->prev;
3599         if (sf->sf_els_list == privp)
3600                 sf->sf_els_list = privp->next;
3601         privp->prev = privp->next = NULL;
3602         mutex_exit(&sf->sf_mutex);
3603         ncmds = fpkt->fcal_ncmds;
3604         ASSERT(ncmds >= 0);
3605         mutex_enter(&sf->sf_cmd_mutex);
3606         sf->sf_ncmds = ncmds;
3607         mutex_exit(&sf->sf_cmd_mutex);
3608 
3609         if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3610                 (void) ddi_dma_sync(privp->rsp_dma_handle, 0,
3611                     0, DDI_DMA_SYNC_FORKERNEL);
3612 
3613                 rsp = (struct fcp_rsp *)privp->rsp;
3614         }
3615         SF_DEBUG(1, (sf, CE_CONT,
3616             "!REPORTLUN to al_pa %x pkt status %x scsi status %x\n",
3617             privp->dest_nport_id,
3618             fpkt->fcal_pkt_status,
3619             rsp?rsp->fcp_u.fcp_status.scsi_status:0));
3620 
3621                 /* See if target simply does not support REPORT_LUNS. */
3622         if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK &&
3623             rsp->fcp_u.fcp_status.sense_len_set &&
3624             rsp->fcp_sense_len >=
3625                 offsetof(struct scsi_extended_sense, es_qual_code)) {
3626                         struct scsi_extended_sense *sense;
3627                         sense = (struct scsi_extended_sense *)
3628                         ((caddr_t)rsp + sizeof (struct fcp_rsp)
3629                                 + rsp->fcp_response_len);
3630                         if (sense->es_key == KEY_ILLEGAL_REQUEST) {
3631                                 if (sense->es_add_code == 0x20) {
3632                                         /* Fake LUN 0 */
3633                                 SF_DEBUG(1, (sf, CE_CONT,
3634                                         "!REPORTLUN Faking good "
3635                                         "completion for alpa %x\n",
3636                                         privp->dest_nport_id));
3637                                         ptr->lun_list_len = FCP_LUN_SIZE;
3638                                         ptr->lun[0] = 0;
3639                                         rsp->fcp_u.fcp_status.scsi_status =
3640                                                 STATUS_GOOD;
3641                                 } else if (sense->es_add_code == 0x25) {
3642                                         SF_DEBUG(1, (sf, CE_CONT,
3643                                             "!REPORTLUN device alpa %x "
3644                                             "key %x code %x\n",
3645                                             privp->dest_nport_id,
3646                                             sense->es_key, sense->es_add_code));
3647                                             goto fail;
3648                                 }
3649                         } else if (sense->es_key ==
3650                                 KEY_UNIT_ATTENTION &&
3651                                 sense->es_add_code == 0x29) {
3652                                 SF_DEBUG(1, (sf, CE_CONT,
3653                                         "!REPORTLUN device alpa %x was reset\n",
3654                                         privp->dest_nport_id));
3655                         } else {
3656                                 SF_DEBUG(1, (sf, CE_CONT,
3657                                         "!REPORTLUN device alpa %x "
3658                                         "key %x code %x\n",
3659                                         privp->dest_nport_id,
3660                                         sense->es_key, sense->es_add_code));
3661 /* XXXXXX The following is here to handle broken targets -- remove it later */
3662                                 if (sf_reportlun_forever &&
3663                                         sense->es_key == KEY_UNIT_ATTENTION)
3664                                         goto retry;
3665 /* XXXXXX */
3666                                 if (sense->es_key == KEY_NOT_READY)
3667                                         delayed_retry = 1;
3668                                 }
3669                 }
3670 
3671         if (rsp && rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) {
3672                 struct fcp_rsp_info *bep;
3673 
3674                 bep = (struct fcp_rsp_info *)(&rsp->
3675                     fcp_response_len + 1);
3676                 if (!rsp->fcp_u.fcp_status.rsp_len_set ||
3677                     bep->rsp_code == FCP_NO_FAILURE) {
3678                         (void) ddi_dma_sync(privp->data_dma_handle,
3679                             0, 0, DDI_DMA_SYNC_FORKERNEL);
3680 
3681                         /* Convert from #bytes to #ints */
3682                         ptr->lun_list_len = ptr->lun_list_len >> 3;
3683                         SF_DEBUG(2, (sf, CE_CONT,
3684                             "!REPORTLUN to al_pa %x succeeded: %d LUNs\n",
3685                             privp->dest_nport_id, ptr->lun_list_len));
3686                         if (!ptr->lun_list_len) {
3687                                 /* No LUNs? Ya gotta be kidding... */
3688                                 sf_log(sf, CE_WARN,
3689                                     "SCSI violation -- "
3690                                     "target 0x%x reports no LUNs\n",
3691                                     sf_alpa_to_switch[
3692                                     privp->dest_nport_id]);
3693                                 ptr->lun_list_len = 1;
3694                                 ptr->lun[0] = 0;
3695                         }
3696 
3697                         mutex_enter(&sf->sf_mutex);
3698                         if (sf->sf_lip_cnt == privp->lip_cnt) {
3699                                 sf->sf_device_count += ptr->lun_list_len - 1;
3700                         }
3701 
3702                         mutex_exit(&sf->sf_mutex);
3703                         for (i = 0; i < ptr->lun_list_len && privp->lip_cnt ==
3704                             sf->sf_lip_cnt; i++) {
3705                                 struct sf_els_hdr *nprivp;
3706                                 struct fcal_packet *nfpkt;
3707 
3708                                 /* LUN 0 is already in `target' */
3709                                 if (ptr->lun[i] != 0) {
3710                                         target = sf_create_target(sf,
3711                                             privp, tid, ptr->lun[i]);
3712                                 }
3713                                 nprivp = NULL;
3714                                 nfpkt = NULL;
3715                                 if (target) {
3716                                         nfpkt = sf_els_alloc(sf,
3717                                             target->sft_al_pa,
3718                                             sizeof (struct sf_els_hdr),
3719                                             sizeof (union sf_els_cmd),
3720                                             sizeof (union sf_els_rsp),
3721                                             (caddr_t *)&nprivp,
3722                                             (caddr_t *)&rsp);
3723                                         if (nprivp)
3724                                                 nprivp->lip_cnt =
3725                                                     privp->lip_cnt;
3726                                 }
3727                                 if (nfpkt && nprivp &&
3728                                     (sf_do_inquiry(sf, nprivp, target) ==
3729                                     0)) {
3730                                         mutex_enter(&sf->sf_mutex);
3731                                         if (sf->sf_lip_cnt == privp->
3732                                             lip_cnt) {
3733                                                 sf->sf_device_count --;
3734                                         }
3735                                         sf_offline_target(sf, target);
3736                                         mutex_exit(&sf->sf_mutex);
3737                                 }
3738                         }
3739                         sf_els_free(fpkt);
3740                         return;
3741                 } else {
3742                         SF_DEBUG(1, (sf, CE_CONT,
3743                             "!REPORTLUN al_pa %x fcp failure, "
3744                             "fcp_rsp_code %x scsi status %x\n",
3745                             privp->dest_nport_id, bep->rsp_code,
3746                             rsp ? rsp->fcp_u.fcp_status.scsi_status:0));
3747                         goto fail;
3748                 }
3749         }
3750         if (rsp && ((rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) ||
3751             (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL))) {
3752                 delayed_retry = 1;
3753         }
3754 
3755         if (++(privp->retries) < sf_els_retries ||
3756             (delayed_retry && privp->retries < SF_BSY_RETRIES)) {
3757 /* XXXXXX The following is here to handle broken targets -- remove it later */
3758 retry:
3759 /* XXXXXX */
3760                 if (delayed_retry) {
3761                         privp->retries--;
3762                         privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT;
3763                         privp->delayed_retry = 1;
3764                 } else {
3765                         privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3766                 }
3767 
3768                 privp->prev = NULL;
3769                 mutex_enter(&sf->sf_mutex);
3770                 if (privp->lip_cnt == sf->sf_lip_cnt) {
3771                         if (!delayed_retry)
3772                                 SF_DEBUG(1, (sf, CE_WARN,
3773                                     "!REPORTLUN to al_pa %x failed, retrying\n",
3774                                     privp->dest_nport_id));
3775                         privp->next = sf->sf_els_list;
3776                         if (sf->sf_els_list != NULL)
3777                                 sf->sf_els_list->prev = privp;
3778                         sf->sf_els_list = privp;
3779                         mutex_exit(&sf->sf_mutex);
3780                         if (!delayed_retry && soc_transport(sf->sf_sochandle,
3781                             fpkt, FCAL_NOSLEEP, CQ_REQUEST_1) !=
3782                             FCAL_TRANSPORT_SUCCESS) {
3783                                 mutex_enter(&sf->sf_mutex);
3784                                 if (privp->prev)
3785                                         privp->prev->next = privp->next;
3786                                 if (privp->next)
3787                                         privp->next->prev = privp->prev;
3788                                 if (sf->sf_els_list == privp)
3789                                         sf->sf_els_list = privp->next;
3790                                 mutex_exit(&sf->sf_mutex);
3791                                 goto fail;
3792                         } else
3793                                 return;
3794                 } else {
3795                         mutex_exit(&sf->sf_mutex);
3796                 }
3797         } else {
3798 fail:
3799 
3800                 /* REPORT_LUN failed -- try inquiry */
3801                 if (sf_do_inquiry(sf, privp, target) != 0) {
3802                         return;
3803                 } else {
3804                         free_pkt = 0;
3805                 }
3806                 mutex_enter(&sf->sf_mutex);
3807                 if (sf->sf_lip_cnt == privp->lip_cnt) {
3808                         sf_log(sf, CE_WARN,
3809                             "!REPORTLUN to target 0x%x failed\n",
3810                             sf_alpa_to_switch[privp->dest_nport_id]);
3811                         sf_offline_target(sf, target);
3812                         sf->sf_device_count--;
3813                         ASSERT(sf->sf_device_count >= 0);
3814                         if (sf->sf_device_count == 0)
3815                         sf_finish_init(sf, privp->lip_cnt);
3816                 }
3817                 mutex_exit(&sf->sf_mutex);
3818         }
3819         if (free_pkt) {
3820                 sf_els_free(fpkt);
3821         }
3822 }
3823 
3824 static int
3825 sf_do_inquiry(struct sf *sf, struct sf_els_hdr *privp,
3826     struct sf_target *target)
3827 {
3828         struct  fcal_packet     *fpkt = privp->fpkt;
3829         ddi_dma_cookie_t        pcookie;
3830         ddi_dma_handle_t        inq_dma_handle = NULL;
3831         ddi_acc_handle_t        inq_acc_handle;
3832         uint_t                  ccount;
3833         size_t                  real_size;
3834         caddr_t                 inq_buf = NULL;
3835         int                     handle_bound = FALSE;
3836         fc_frame_header_t *hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
3837         struct fcp_cmd          *inq = (struct fcp_cmd *)privp->cmd;
3838         char                    *msg = "Transport";
3839 
3840 
3841         if (ddi_dma_alloc_handle(sf->sf_dip, sf->sf_sochandle->fcal_dmaattr,
3842             DDI_DMA_DONTWAIT, NULL, &inq_dma_handle) != DDI_SUCCESS) {
3843                 msg = "ddi_dma_alloc_handle()";
3844                 goto fail;
3845         }
3846 
3847         if (ddi_dma_mem_alloc(inq_dma_handle, SUN_INQSIZE,
3848             sf->sf_sochandle->fcal_accattr, DDI_DMA_CONSISTENT,
3849             DDI_DMA_DONTWAIT, NULL, &inq_buf,
3850             &real_size, &inq_acc_handle) != DDI_SUCCESS) {
3851                 msg = "ddi_dma_mem_alloc()";
3852                 goto fail;
3853         }
3854 
3855         if (real_size < SUN_INQSIZE) {
3856                 msg = "DMA mem < inquiry size";
3857                 goto fail;
3858         }
3859 
3860         if (ddi_dma_addr_bind_handle(inq_dma_handle, NULL,
3861             inq_buf, real_size, DDI_DMA_READ | DDI_DMA_CONSISTENT,
3862             DDI_DMA_DONTWAIT, NULL, &pcookie, &ccount) != DDI_DMA_MAPPED) {
3863                 msg = "ddi_dma_addr_bind_handle()";
3864                 goto fail;
3865         }
3866         handle_bound = TRUE;
3867 
3868         if (ccount != 1) {
3869                 msg = "ccount != 1";
3870                 goto fail;
3871         }
3872         privp->els_code = 0;                 /* not an ELS command */
3873         privp->target = target;
3874         privp->data_dma_handle = inq_dma_handle;
3875         privp->data_acc_handle = inq_acc_handle;
3876         privp->data_buf = inq_buf;
3877         fpkt->fcal_pkt_comp = sf_inq_callback;
3878         fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 3;
3879         fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type = CQ_TYPE_IO_READ;
3880         fpkt->fcal_socal_request.sr_dataseg[0].fc_count =
3881             sizeof (struct fcp_cmd);
3882         fpkt->fcal_socal_request.sr_dataseg[2].fc_base =
3883             (uint32_t)pcookie.dmac_address;
3884         fpkt->fcal_socal_request.sr_dataseg[2].fc_count = pcookie.dmac_size;
3885         fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt = pcookie.dmac_size;
3886         hp->r_ctl = R_CTL_COMMAND;
3887         hp->type = TYPE_SCSI_FCP;
3888         bzero((caddr_t)inq, sizeof (struct fcp_cmd));
3889         ((union scsi_cdb *)inq->fcp_cdb)->scc_cmd = SCMD_INQUIRY;
3890         ((union scsi_cdb *)inq->fcp_cdb)->g0_count0 = SUN_INQSIZE;
3891         bcopy((caddr_t)&target->sft_lun.b, (caddr_t)&inq->fcp_ent_addr,
3892             FCP_LUN_SIZE);
3893         inq->fcp_cntl.cntl_read_data = 1;
3894         inq->fcp_cntl.cntl_write_data = 0;
3895         inq->fcp_data_len = pcookie.dmac_size;
3896         inq->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
3897 
3898         (void) ddi_dma_sync(inq_dma_handle, (off_t)0, (size_t)0,
3899             DDI_DMA_SYNC_FORDEV);
3900         privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
3901         SF_DEBUG(5, (sf, CE_WARN,
3902             "!Sending INQUIRY to al_pa %x lun %" PRIx64 "\n",
3903             privp->dest_nport_id,
3904             SCSA_LUN(target)));
3905         return (sf_els_transport(sf, privp));
3906 
3907 fail:
3908         sf_log(sf, CE_WARN,
3909             "%s failure for INQUIRY to target 0x%x\n",
3910             msg, sf_alpa_to_switch[privp->dest_nport_id]);
3911         sf_els_free(fpkt);
3912         if (inq_dma_handle != NULL) {
3913                 if (handle_bound) {
3914                         (void) ddi_dma_unbind_handle(inq_dma_handle);
3915                 }
3916                 ddi_dma_free_handle(&inq_dma_handle);
3917         }
3918         if (inq_buf != NULL) {
3919                 ddi_dma_mem_free(&inq_acc_handle);
3920         }
3921         return (FALSE);
3922 }
3923 
3924 
3925 /*
3926  * called as the pkt_comp routine for INQ packets
3927  */
3928 static void
3929 sf_inq_callback(struct fcal_packet *fpkt)
3930 {
3931         struct sf_els_hdr *privp = (struct sf_els_hdr *)fpkt->
3932             fcal_pkt_private;
3933         struct scsi_inquiry *prt = (struct scsi_inquiry *)privp->data_buf;
3934         struct sf *sf = privp->sf;
3935         struct sf *tsf;
3936         struct sf_target *target = privp->target;
3937         struct fcp_rsp *rsp;
3938         int delayed_retry = FALSE;
3939         short   ncmds;
3940 
3941 
3942         mutex_enter(&sf->sf_mutex);
3943         /* use as temporary state variable */
3944         if (privp->timeout == SF_INVALID_TIMEOUT) {
3945                 mutex_exit(&sf->sf_mutex);
3946                 return;
3947         }
3948         if (privp->prev != NULL) {
3949                 privp->prev->next = privp->next;
3950         }
3951         if (privp->next != NULL) {
3952                 privp->next->prev = privp->prev;
3953         }
3954         if (sf->sf_els_list == privp) {
3955                 sf->sf_els_list = privp->next;
3956         }
3957         privp->prev = privp->next = NULL;
3958         mutex_exit(&sf->sf_mutex);
3959         ncmds = fpkt->fcal_ncmds;
3960         ASSERT(ncmds >= 0);
3961         mutex_enter(&sf->sf_cmd_mutex);
3962         sf->sf_ncmds = ncmds;
3963         mutex_exit(&sf->sf_cmd_mutex);
3964 
3965         if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
3966 
3967                 (void) ddi_dma_sync(privp->rsp_dma_handle, (off_t)0,
3968                     (size_t)0, DDI_DMA_SYNC_FORKERNEL);
3969 
3970                 rsp = (struct fcp_rsp *)privp->rsp;
3971                 SF_DEBUG(2, (sf, CE_CONT,
3972                     "!INQUIRY to al_pa %x scsi status %x",
3973                     privp->dest_nport_id, rsp->fcp_u.fcp_status.scsi_status));
3974 
3975                 if ((rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD) &&
3976                     !rsp->fcp_u.fcp_status.resid_over &&
3977                     (!rsp->fcp_u.fcp_status.resid_under ||
3978                     ((SUN_INQSIZE - rsp->fcp_resid) >= SUN_MIN_INQLEN))) {
3979                         struct fcp_rsp_info *bep;
3980 
3981                         bep = (struct fcp_rsp_info *)(&rsp->
3982                             fcp_response_len + 1);
3983 
3984                         if (!rsp->fcp_u.fcp_status.rsp_len_set ||
3985                             (bep->rsp_code == FCP_NO_FAILURE)) {
3986 
3987                                 SF_DEBUG(2, (sf, CE_CONT,
3988                                     "!INQUIRY to al_pa %x lun %" PRIx64
3989                                     " succeeded\n",
3990                                     privp->dest_nport_id, SCSA_LUN(target)));
3991 
3992                                 (void) ddi_dma_sync(privp->data_dma_handle,
3993                                     (off_t)0, (size_t)0,
3994                                     DDI_DMA_SYNC_FORKERNEL);
3995 
3996                                 mutex_enter(&sf->sf_mutex);
3997 
3998                                 if (sf->sf_lip_cnt == privp->lip_cnt) {
3999                                         mutex_enter(&target->sft_mutex);
4000                                         target->sft_device_type =
4001                                             prt->inq_dtype;
4002                                         bcopy(prt, &target->sft_inq,
4003                                             sizeof (*prt));
4004                                         mutex_exit(&target->sft_mutex);
4005                                         sf->sf_device_count--;
4006                                         ASSERT(sf->sf_device_count >= 0);
4007                                         if (sf->sf_device_count == 0) {
4008                                                 sf_finish_init(sf,
4009                                                     privp->lip_cnt);
4010                                         }
4011                                 }
4012                                 mutex_exit(&sf->sf_mutex);
4013                                 sf_els_free(fpkt);
4014                                 return;
4015                         }
4016                 } else if ((rsp->fcp_u.fcp_status.scsi_status ==
4017                     STATUS_BUSY) ||
4018                     (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL) ||
4019                     (rsp->fcp_u.fcp_status.scsi_status == STATUS_CHECK)) {
4020                         delayed_retry = TRUE;
4021                 }
4022         } else {
4023                 SF_DEBUG(2, (sf, CE_CONT, "!INQUIRY to al_pa %x fc status %x",
4024                     privp->dest_nport_id, fpkt->fcal_pkt_status));
4025         }
4026 
4027         if (++(privp->retries) < sf_els_retries ||
4028             (delayed_retry && privp->retries < SF_BSY_RETRIES)) {
4029                 if (fpkt->fcal_pkt_status == FCAL_STATUS_MAX_XCHG_EXCEEDED)  {
4030                         tsf = sf->sf_sibling;
4031                         if (tsf != NULL) {
4032                                 mutex_enter(&tsf->sf_cmd_mutex);
4033                                 tsf->sf_flag = 1;
4034                                 tsf->sf_throttle = SF_DECR_DELTA;
4035                                 mutex_exit(&tsf->sf_cmd_mutex);
4036                         }
4037                         delayed_retry = 1;
4038                 }
4039                 if (delayed_retry) {
4040                         privp->retries--;
4041                         privp->timeout = sf_watchdog_time + SF_BSY_TIMEOUT;
4042                         privp->delayed_retry = TRUE;
4043                 } else {
4044                         privp->timeout = sf_watchdog_time + SF_FCP_TIMEOUT;
4045                 }
4046 
4047                 privp->prev = NULL;
4048                 mutex_enter(&sf->sf_mutex);
4049                 if (privp->lip_cnt == sf->sf_lip_cnt) {
4050                         if (!delayed_retry) {
4051                                 SF_DEBUG(1, (sf, CE_WARN,
4052                                     "INQUIRY to al_pa %x failed, retrying",
4053                                     privp->dest_nport_id));
4054                         }
4055                         privp->next = sf->sf_els_list;
4056                         if (sf->sf_els_list != NULL) {
4057                                 sf->sf_els_list->prev = privp;
4058                         }
4059                         sf->sf_els_list = privp;
4060                         mutex_exit(&sf->sf_mutex);
4061                         /* if not delayed call transport to send a pkt */
4062                         if (!delayed_retry &&
4063                             (soc_transport(sf->sf_sochandle, fpkt,
4064                             FCAL_NOSLEEP, CQ_REQUEST_1) !=
4065                             FCAL_TRANSPORT_SUCCESS)) {
4066                                 mutex_enter(&sf->sf_mutex);
4067                                 if (privp->prev != NULL) {
4068                                         privp->prev->next = privp->next;
4069                                 }
4070                                 if (privp->next != NULL) {
4071                                         privp->next->prev = privp->prev;
4072                                 }
4073                                 if (sf->sf_els_list == privp) {
4074                                         sf->sf_els_list = privp->next;
4075                                 }
4076                                 mutex_exit(&sf->sf_mutex);
4077                                 goto fail;
4078                         }
4079                         return;
4080                 }
4081                 mutex_exit(&sf->sf_mutex);
4082         } else {
4083 fail:
4084                 mutex_enter(&sf->sf_mutex);
4085                 if (sf->sf_lip_cnt == privp->lip_cnt) {
4086                         sf_offline_target(sf, target);
4087                         sf_log(sf, CE_NOTE,
4088                             "INQUIRY to target 0x%x lun %" PRIx64 " failed. "
4089                             "Retry Count: %d\n",
4090                             sf_alpa_to_switch[privp->dest_nport_id],
4091                             SCSA_LUN(target),
4092                             privp->retries);
4093                         sf->sf_device_count--;
4094                         ASSERT(sf->sf_device_count >= 0);
4095                         if (sf->sf_device_count == 0) {
4096                                 sf_finish_init(sf, privp->lip_cnt);
4097                         }
4098                 }
4099                 mutex_exit(&sf->sf_mutex);
4100         }
4101         sf_els_free(fpkt);
4102 }
4103 
4104 
4105 static void
4106 sf_finish_init(struct sf *sf, int lip_cnt)
4107 {
4108         int                     i;              /* loop index */
4109         int                     cflag;
4110         struct sf_target        *target;        /* current target */
4111         dev_info_t              *dip;
4112         struct sf_hp_elem       *elem;          /* hotplug element created */
4113 
4114         SF_DEBUG(1, (sf, CE_WARN, "!sf_finish_init\n"));
4115         ASSERT(mutex_owned(&sf->sf_mutex));
4116 
4117         /* scan all hash queues */
4118         for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
4119                 target = sf->sf_wwn_lists[i];
4120                 while (target != NULL) {
4121                         mutex_enter(&target->sft_mutex);
4122 
4123                         /* see if target is not offline */
4124                         if ((target->sft_state & SF_TARGET_OFFLINE)) {
4125                                 /*
4126                                  * target already offline
4127                                  */
4128                                 mutex_exit(&target->sft_mutex);
4129                                 goto next_entry;
4130                         }
4131 
4132                         /*
4133                          * target is not already offline -- see if it has
4134                          * already been marked as ready to go offline
4135                          */
4136                         if (target->sft_state & SF_TARGET_MARK) {
4137                                 /*
4138                                  * target already marked, so take it offline
4139                                  */
4140                                 mutex_exit(&target->sft_mutex);
4141                                 sf_offline_target(sf, target);
4142                                 goto next_entry;
4143                         }
4144 
4145                         /* clear target busy flag */
4146                         target->sft_state &= ~SF_TARGET_BUSY;
4147 
4148                         /* is target init not yet done ?? */
4149                         cflag = !(target->sft_state & SF_TARGET_INIT_DONE);
4150 
4151                         /* get pointer to target dip */
4152                         dip = target->sft_dip;
4153 
4154                         mutex_exit(&target->sft_mutex);
4155                         mutex_exit(&sf->sf_mutex);
4156 
4157                         if (cflag && (dip == NULL)) {
4158                                 /*
4159                                  * target init not yet done &&
4160                                  * devinfo not yet created
4161                                  */
4162                                 sf_create_devinfo(sf, target, lip_cnt);
4163                                 mutex_enter(&sf->sf_mutex);
4164                                 goto next_entry;
4165                         }
4166 
4167                         /*
4168                          * target init already done || devinfo already created
4169                          */
4170                         ASSERT(dip != NULL);
4171                         if (!sf_create_props(dip, target, lip_cnt)) {
4172                                 /* a problem creating properties */
4173                                 mutex_enter(&sf->sf_mutex);
4174                                 goto next_entry;
4175                         }
4176 
4177                         /* create a new element for the hotplug list */
4178                         if ((elem = kmem_zalloc(sizeof (struct sf_hp_elem),
4179                             KM_NOSLEEP)) != NULL) {
4180 
4181                                 /* fill in the new element */
4182                                 elem->dip = dip;
4183                                 elem->target = target;
4184                                 elem->what = SF_ONLINE;
4185 
4186                                 /* add the new element into the hotplug list */
4187                                 mutex_enter(&sf->sf_hp_daemon_mutex);
4188                                 if (sf->sf_hp_elem_tail != NULL) {
4189                                         sf->sf_hp_elem_tail->next = elem;
4190                                         sf->sf_hp_elem_tail = elem;
4191                                 } else {
4192                                         /* this is the first element in list */
4193                                         sf->sf_hp_elem_head =
4194                                             sf->sf_hp_elem_tail =
4195                                             elem;
4196                                 }
4197                                 cv_signal(&sf->sf_hp_daemon_cv);
4198                                 mutex_exit(&sf->sf_hp_daemon_mutex);
4199                         } else {
4200                                 /* could not allocate memory for element ?? */
4201                                 (void) ndi_devi_online_async(dip, 0);
4202                         }
4203 
4204                         mutex_enter(&sf->sf_mutex);
4205 
4206 next_entry:
4207                         /* ensure no new LIPs have occurred */
4208                         if (sf->sf_lip_cnt != lip_cnt) {
4209                                 return;
4210                         }
4211                         target = target->sft_next;
4212                 }
4213 
4214                 /* done scanning all targets in this queue */
4215         }
4216 
4217         /* done with all hash queues */
4218 
4219         sf->sf_state = SF_STATE_ONLINE;
4220         sf->sf_online_timer = 0;
4221 }
4222 
4223 
4224 /*
4225  * create devinfo node
4226  */
4227 static void
4228 sf_create_devinfo(struct sf *sf, struct sf_target *target, int lip_cnt)
4229 {
4230         dev_info_t              *cdip = NULL;
4231         char                    *nname = NULL;
4232         char                    **compatible = NULL;
4233         int                     ncompatible;
4234         struct scsi_inquiry     *inq = &target->sft_inq;
4235         char                    *scsi_binding_set;
4236 
4237         /* get the 'scsi-binding-set' property */
4238         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, sf->sf_dip,
4239             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
4240             &scsi_binding_set) != DDI_PROP_SUCCESS)
4241                 scsi_binding_set = NULL;
4242 
4243         /* determine the node name and compatible */
4244         scsi_hba_nodename_compatible_get(inq, scsi_binding_set,
4245             inq->inq_dtype, NULL, &nname, &compatible, &ncompatible);
4246         if (scsi_binding_set)
4247                 ddi_prop_free(scsi_binding_set);
4248 
4249         /* if nodename can't be determined then print a message and skip it */
4250         if (nname == NULL) {
4251 #ifndef RAID_LUNS
4252                 sf_log(sf, CE_WARN, "%s%d: no driver for device "
4253                     "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n"
4254                     "    compatible: %s",
4255                     ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip),
4256                     target->sft_port_wwn[0], target->sft_port_wwn[1],
4257                     target->sft_port_wwn[2], target->sft_port_wwn[3],
4258                     target->sft_port_wwn[4], target->sft_port_wwn[5],
4259                     target->sft_port_wwn[6], target->sft_port_wwn[7],
4260                     target->sft_lun.l, *compatible);
4261 #else
4262                 sf_log(sf, CE_WARN, "%s%d: no driver for device "
4263                     "@w%02x%02x%02x%02x%02x%02x%02x%02x,%x\n"
4264                     "    compatible: %s",
4265                     ddi_driver_name(sf->sf_dip), ddi_get_instance(sf->sf_dip),
4266                     target->sft_port_wwn[0], target->sft_port_wwn[1],
4267                     target->sft_port_wwn[2], target->sft_port_wwn[3],
4268                     target->sft_port_wwn[4], target->sft_port_wwn[5],
4269                     target->sft_port_wwn[6], target->sft_port_wwn[7],
4270                     target->sft_raid_lun, *compatible);
4271 #endif
4272                 goto fail;
4273         }
4274 
4275         /* allocate the node */
4276         if (ndi_devi_alloc(sf->sf_dip, nname,
4277             DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
4278                 goto fail;
4279         }
4280 
4281         /* decorate the node with compatible */
4282         if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
4283             "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
4284                 goto fail;
4285         }
4286 
4287         /* add addressing properties to the node */
4288         if (sf_create_props(cdip, target, lip_cnt) != 1) {
4289                 goto fail;
4290         }
4291 
4292         mutex_enter(&target->sft_mutex);
4293         if (target->sft_dip != NULL) {
4294                 mutex_exit(&target->sft_mutex);
4295                 goto fail;
4296         }
4297         target->sft_dip = cdip;
4298         mutex_exit(&target->sft_mutex);
4299 
4300         if (ndi_devi_online_async(cdip, 0) != DDI_SUCCESS) {
4301                 goto fail;
4302         }
4303 
4304         scsi_hba_nodename_compatible_free(nname, compatible);
4305         return;
4306 
4307 fail:
4308         scsi_hba_nodename_compatible_free(nname, compatible);
4309         if (cdip != NULL) {
4310                 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP);
4311                 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP);
4312                 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LIP_CNT_PROP);
4313                 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, TARGET_PROP);
4314                 (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, LUN_PROP);
4315                 if (ndi_devi_free(cdip) != NDI_SUCCESS) {
4316                         sf_log(sf, CE_WARN, "ndi_devi_free failed\n");
4317                 } else {
4318                         mutex_enter(&target->sft_mutex);
4319                         if (cdip == target->sft_dip) {
4320                                 target->sft_dip = NULL;
4321                         }
4322                         mutex_exit(&target->sft_mutex);
4323                 }
4324         }
4325 }
4326 
4327 /*
4328  * create required properties, returning TRUE iff we succeed, else
4329  * returning FALSE
4330  */
4331 static int
4332 sf_create_props(dev_info_t *cdip, struct sf_target *target, int lip_cnt)
4333 {
4334         int tgt_id = sf_alpa_to_switch[target->sft_al_pa];
4335 
4336 
4337         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
4338             cdip, NODE_WWN_PROP, target->sft_node_wwn, FC_WWN_SIZE) !=
4339             DDI_PROP_SUCCESS) {
4340                 return (FALSE);
4341         }
4342 
4343         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
4344             cdip, PORT_WWN_PROP, target->sft_port_wwn, FC_WWN_SIZE) !=
4345             DDI_PROP_SUCCESS) {
4346                 return (FALSE);
4347         }
4348 
4349         if (ndi_prop_update_int(DDI_DEV_T_NONE,
4350             cdip, LIP_CNT_PROP, lip_cnt) != DDI_PROP_SUCCESS) {
4351                 return (FALSE);
4352         }
4353 
4354         if (ndi_prop_update_int(DDI_DEV_T_NONE,
4355             cdip, TARGET_PROP, tgt_id) != DDI_PROP_SUCCESS) {
4356                 return (FALSE);
4357         }
4358 
4359 #ifndef RAID_LUNS
4360         if (ndi_prop_update_int(DDI_DEV_T_NONE,
4361             cdip, LUN_PROP, target->sft_lun.l) != DDI_PROP_SUCCESS) {
4362                 return (0);
4363         }
4364 #else
4365         if (ndi_prop_update_int(DDI_DEV_T_NONE,
4366             cdip, LUN_PROP, target->sft_raid_lun) != DDI_PROP_SUCCESS) {
4367                 return (0);
4368         }
4369 #endif
4370 
4371         return (TRUE);
4372 }
4373 
4374 
4375 /*
4376  * called by the transport to offline a target
4377  */
4378 /* ARGSUSED */
4379 static void
4380 sf_offline_target(struct sf *sf, struct sf_target *target)
4381 {
4382         dev_info_t *dip;
4383         struct sf_target *next_target = NULL;
4384         struct sf_hp_elem       *elem;
4385 
4386         ASSERT(mutex_owned(&sf->sf_mutex));
4387 
4388         if (sf_core && (sf_core & SF_CORE_OFFLINE_TARGET)) {
4389                 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
4390                 sf_core = 0;
4391         }
4392 
4393         while (target != NULL) {
4394                 sf_log(sf, CE_NOTE,
4395                     "!target 0x%x al_pa 0x%x lun %" PRIx64 " offlined\n",
4396                     sf_alpa_to_switch[target->sft_al_pa],
4397                     target->sft_al_pa, SCSA_LUN(target));
4398                 mutex_enter(&target->sft_mutex);
4399                 target->sft_state &= ~(SF_TARGET_BUSY|SF_TARGET_MARK);
4400                 target->sft_state |= SF_TARGET_OFFLINE;
4401                 mutex_exit(&target->sft_mutex);
4402                 mutex_exit(&sf->sf_mutex);
4403 
4404                 /* XXXX if this is LUN 0, offline all other LUNs */
4405                 if (next_target || target->sft_lun.l == 0)
4406                         next_target = target->sft_next_lun;
4407 
4408                 /* abort all cmds for this target */
4409                 sf_abort_all(sf, target, FALSE, sf->sf_lip_cnt, FALSE);
4410 
4411                 mutex_enter(&sf->sf_mutex);
4412                 mutex_enter(&target->sft_mutex);
4413                 if (target->sft_state & SF_TARGET_INIT_DONE) {
4414                         dip = target->sft_dip;
4415                         mutex_exit(&target->sft_mutex);
4416                         mutex_exit(&sf->sf_mutex);
4417                         (void) ndi_prop_remove(DDI_DEV_T_NONE, dip,
4418                             TARGET_PROP);
4419                         (void) ndi_event_retrieve_cookie(sf->sf_event_hdl,
4420                             dip, FCAL_REMOVE_EVENT, &sf_remove_eid,
4421                             NDI_EVENT_NOPASS);
4422                         (void) ndi_event_run_callbacks(sf->sf_event_hdl,
4423                             target->sft_dip, sf_remove_eid, NULL);
4424 
4425                         elem = kmem_zalloc(sizeof (struct sf_hp_elem),
4426                             KM_NOSLEEP);
4427                         if (elem != NULL) {
4428                                 elem->dip = dip;
4429                                 elem->target = target;
4430                                 elem->what = SF_OFFLINE;
4431                                 mutex_enter(&sf->sf_hp_daemon_mutex);
4432                                 if (sf->sf_hp_elem_tail != NULL) {
4433                                         sf->sf_hp_elem_tail->next = elem;
4434                                         sf->sf_hp_elem_tail = elem;
4435                                 } else {
4436                                         sf->sf_hp_elem_head =
4437                                             sf->sf_hp_elem_tail =
4438                                             elem;
4439                                 }
4440                                 cv_signal(&sf->sf_hp_daemon_cv);
4441                                 mutex_exit(&sf->sf_hp_daemon_mutex);
4442                         } else {
4443                                 /* don't do NDI_DEVI_REMOVE for now */
4444                                 if (ndi_devi_offline(dip, 0) != NDI_SUCCESS) {
4445                                         SF_DEBUG(1, (sf, CE_WARN,
4446                                             "target %x lun %" PRIx64 ", "
4447                                             "device offline failed",
4448                                             sf_alpa_to_switch[target->
4449                                             sft_al_pa],
4450                                             SCSA_LUN(target)));
4451                                 } else {
4452                                         SF_DEBUG(1, (sf, CE_NOTE,
4453                                             "target %x, lun %" PRIx64 ", "
4454                                             "device offline succeeded\n",
4455                                             sf_alpa_to_switch[target->
4456                                             sft_al_pa],
4457                                             SCSA_LUN(target)));
4458                                 }
4459                         }
4460                         mutex_enter(&sf->sf_mutex);
4461                 } else {
4462                         mutex_exit(&target->sft_mutex);
4463                 }
4464                 target = next_target;
4465         }
4466 }
4467 
4468 
4469 /*
4470  * routine to get/set a capability
4471  *
4472  * returning:
4473  *      1 (TRUE)        boolean capability is true (on get)
4474  *      0 (FALSE)       invalid capability, can't set capability (on set),
4475  *                      or boolean capability is false (on get)
4476  *      -1 (UNDEFINED)  can't find capability (SCSA) or unsupported capability
4477  *      3               when getting SCSI version number
4478  *      AL_PA           when getting port initiator ID
4479  */
4480 static int
4481 sf_commoncap(struct scsi_address *ap, char *cap,
4482     int val, int tgtonly, int doset)
4483 {
4484         struct sf *sf = ADDR2SF(ap);
4485         int cidx;
4486         int rval = FALSE;
4487 
4488 
4489         if (cap == NULL) {
4490                 SF_DEBUG(3, (sf, CE_WARN, "sf_commoncap: invalid arg"));
4491                 return (rval);
4492         }
4493 
4494         /* get index of capability string */
4495         if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
4496                 /* can't find capability */
4497                 return (UNDEFINED);
4498         }
4499 
4500         if (doset) {
4501                 /*
4502                  * Process setcap request.
4503                  */
4504 
4505                 /*
4506                  * At present, we can only set binary (0/1) values
4507                  */
4508                 switch (cidx) {
4509                 case SCSI_CAP_ARQ:      /* can't set this capability */
4510                         break;
4511                 default:
4512                         SF_DEBUG(3, (sf, CE_WARN,
4513                             "sf_setcap: unsupported %d", cidx));
4514                         rval = UNDEFINED;
4515                         break;
4516                 }
4517 
4518                 SF_DEBUG(4, (sf, CE_NOTE,
4519                     "set cap: cap=%s,val=0x%x,tgtonly=0x%x"
4520                     ",doset=0x%x,rval=%d\n",
4521                     cap, val, tgtonly, doset, rval));
4522 
4523         } else {
4524                 /*
4525                  * Process getcap request.
4526                  */
4527                 switch (cidx) {
4528                 case SCSI_CAP_DMA_MAX:
4529                         break;          /* don't' have this capability */
4530                 case SCSI_CAP_INITIATOR_ID:
4531                         rval = sf->sf_al_pa;
4532                         break;
4533                 case SCSI_CAP_ARQ:
4534                         rval = TRUE;    /* do have this capability */
4535                         break;
4536                 case SCSI_CAP_RESET_NOTIFICATION:
4537                 case SCSI_CAP_TAGGED_QING:
4538                         rval = TRUE;    /* do have this capability */
4539                         break;
4540                 case SCSI_CAP_SCSI_VERSION:
4541                         rval = 3;
4542                         break;
4543                 case SCSI_CAP_INTERCONNECT_TYPE:
4544                         rval = INTERCONNECT_FIBRE;
4545                         break;
4546                 default:
4547                         SF_DEBUG(4, (sf, CE_WARN,
4548                             "sf_scsi_getcap: unsupported"));
4549                         rval = UNDEFINED;
4550                         break;
4551                 }
4552                 SF_DEBUG(4, (sf, CE_NOTE,
4553                     "get cap: cap=%s,val=0x%x,tgtonly=0x%x,"
4554                     "doset=0x%x,rval=%d\n",
4555                     cap, val, tgtonly, doset, rval));
4556         }
4557 
4558         return (rval);
4559 }
4560 
4561 
4562 /*
4563  * called by the transport to get a capability
4564  */
4565 static int
4566 sf_getcap(struct scsi_address *ap, char *cap, int whom)
4567 {
4568         return (sf_commoncap(ap, cap, 0, whom, FALSE));
4569 }
4570 
4571 
4572 /*
4573  * called by the transport to set a capability
4574  */
4575 static int
4576 sf_setcap(struct scsi_address *ap, char *cap, int value, int whom)
4577 {
4578         return (sf_commoncap(ap, cap, value, whom, TRUE));
4579 }
4580 
4581 
4582 /*
4583  * called by the transport to abort a target
4584  */
4585 static int
4586 sf_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
4587 {
4588         struct sf *sf = ADDR2SF(ap);
4589         struct sf_target *target = ADDR2TARGET(ap);
4590         struct sf_pkt *cmd, *ncmd, *pcmd;
4591         struct fcal_packet *fpkt;
4592         int     rval = 0, t, my_rval = FALSE;
4593         int     old_target_state;
4594         int     lip_cnt;
4595         int     tgt_id;
4596         fc_frame_header_t       *hp;
4597         int     deferred_destroy;
4598 
4599         deferred_destroy = 0;
4600 
4601         if (pkt != NULL) {
4602                 cmd = PKT2CMD(pkt);
4603                 fpkt = cmd->cmd_fp_pkt;
4604                 SF_DEBUG(2, (sf, CE_NOTE, "sf_abort packet %p\n",
4605                     (void *)fpkt));
4606                 pcmd = NULL;
4607                 mutex_enter(&sf->sf_cmd_mutex);
4608                 ncmd = sf->sf_pkt_head;
4609                 while (ncmd != NULL) {
4610                         if (ncmd == cmd) {
4611                                 if (pcmd != NULL) {
4612                                         pcmd->cmd_next = cmd->cmd_next;
4613                                 } else {
4614                                         sf->sf_pkt_head = cmd->cmd_next;
4615                                 }
4616                                 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
4617                                 cmd->cmd_state = SF_STATE_IDLE;
4618                                 pkt->pkt_reason = CMD_ABORTED;
4619                                 pkt->pkt_statistics |= STAT_ABORTED;
4620                                 my_rval = TRUE;
4621                                 break;
4622                         } else {
4623                                 pcmd = ncmd;
4624                                 ncmd = ncmd->cmd_next;
4625                         }
4626                 }
4627                 mutex_exit(&sf->sf_cmd_mutex);
4628                 if (ncmd == NULL) {
4629                         mutex_enter(&cmd->cmd_abort_mutex);
4630                         if (cmd->cmd_state == SF_STATE_ISSUED) {
4631                                 cmd->cmd_state = SF_STATE_ABORTING;
4632                                 cmd->cmd_timeout = sf_watchdog_time + 20;
4633                                 mutex_exit(&cmd->cmd_abort_mutex);
4634                                 /* call transport to abort command */
4635                                 if (((rval = soc_abort(sf->sf_sochandle,
4636                                     sf->sf_socp, sf->sf_sochandle->fcal_portno,
4637                                     fpkt, 1)) == FCAL_ABORTED) ||
4638                                     (rval == FCAL_ABORT_FAILED)) {
4639                                         my_rval = TRUE;
4640                                         pkt->pkt_reason = CMD_ABORTED;
4641                                         pkt->pkt_statistics |= STAT_ABORTED;
4642                                         cmd->cmd_state = SF_STATE_IDLE;
4643                                 } else if (rval == FCAL_BAD_ABORT) {
4644                                         cmd->cmd_timeout = sf_watchdog_time
4645                                             + 20;
4646                                         my_rval = FALSE;
4647                                 } else {
4648                                         SF_DEBUG(1, (sf, CE_NOTE,
4649                                             "Command Abort failed\n"));
4650                                 }
4651                         } else {
4652                                 mutex_exit(&cmd->cmd_abort_mutex);
4653                         }
4654                 }
4655         } else {
4656                 SF_DEBUG(2, (sf, CE_NOTE, "sf_abort target\n"));
4657                 mutex_enter(&sf->sf_mutex);
4658                 lip_cnt = sf->sf_lip_cnt;
4659                 mutex_enter(&target->sft_mutex);
4660                 if (target->sft_state & (SF_TARGET_BUSY |
4661                     SF_TARGET_OFFLINE)) {
4662                         mutex_exit(&target->sft_mutex);
4663                         return (rval);
4664                 }
4665                 old_target_state = target->sft_state;
4666                 target->sft_state |= SF_TARGET_BUSY;
4667                 mutex_exit(&target->sft_mutex);
4668                 mutex_exit(&sf->sf_mutex);
4669 
4670                 if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0,
4671                     0, 0, 0, NULL, 0)) != NULL) {
4672 
4673                         cmd = PKT2CMD(pkt);
4674                         cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 1;
4675                         cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
4676                         cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
4677 
4678                         /* prepare the packet for transport */
4679                         if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) {
4680 
4681                                 cmd->cmd_state = SF_STATE_ISSUED;
4682                                 /*
4683                                  * call transport to send a pkt polled
4684                                  *
4685                                  * if that fails call the transport to abort it
4686                                  */
4687                                 if (soc_transport_poll(sf->sf_sochandle,
4688                                     cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT,
4689                                     CQ_REQUEST_1) == FCAL_TRANSPORT_SUCCESS) {
4690                                         (void) ddi_dma_sync(
4691                                             cmd->cmd_cr_pool->rsp_dma_handle,
4692                                             (off_t)
4693                                             ((caddr_t)cmd->cmd_rsp_block -
4694                                             cmd->cmd_cr_pool->rsp_base),
4695                                             FCP_MAX_RSP_IU_SIZE,
4696                                             DDI_DMA_SYNC_FORKERNEL);
4697                                         if (((struct fcp_rsp_info *)
4698                                             (&cmd->cmd_rsp_block->
4699                                             fcp_response_len + 1))->
4700                                             rsp_code == FCP_NO_FAILURE) {
4701                                                 /* abort cmds for this targ */
4702                                                 sf_abort_all(sf, target, TRUE,
4703                                                     lip_cnt, TRUE);
4704                                         } else {
4705                                                 hp = &cmd->cmd_fp_pkt->
4706                                                     fcal_socal_request.
4707                                                     sr_fc_frame_hdr;
4708                                                 tgt_id = sf_alpa_to_switch[
4709                                                     (uchar_t)hp->d_id];
4710                                                 sf->sf_stats.tstats[tgt_id].
4711                                                     task_mgmt_failures++;
4712                                                 SF_DEBUG(1, (sf, CE_NOTE,
4713                                                     "Target %d Abort Task "
4714                                                     "Set failed\n", hp->d_id));
4715                                         }
4716                                 } else {
4717                                         mutex_enter(&cmd->cmd_abort_mutex);
4718                                         if (cmd->cmd_state == SF_STATE_ISSUED) {
4719                                         cmd->cmd_state = SF_STATE_ABORTING;
4720                                         cmd->cmd_timeout = sf_watchdog_time
4721                                             + 20;
4722                                         mutex_exit(&cmd->cmd_abort_mutex);
4723                                         if ((t = soc_abort(sf->sf_sochandle,
4724                                             sf->sf_socp, sf->sf_sochandle->
4725                                             fcal_portno, cmd->cmd_fp_pkt, 1)) !=
4726                                             FCAL_ABORTED &&
4727                                             (t != FCAL_ABORT_FAILED)) {
4728                                                 sf_log(sf, CE_NOTE,
4729                                                     "sf_abort failed, "
4730                                                     "initiating LIP\n");
4731                                                 sf_force_lip(sf);
4732                                                 deferred_destroy = 1;
4733                                         }
4734                                         } else {
4735                                         mutex_exit(&cmd->cmd_abort_mutex);
4736                                         }
4737                                 }
4738                         }
4739                         if (!deferred_destroy) {
4740                                 cmd->cmd_fp_pkt->fcal_pkt_comp =
4741                                     sf_cmd_callback;
4742                                 cmd->cmd_block->fcp_cntl.cntl_abort_tsk = 0;
4743                                 sf_scsi_destroy_pkt(ap, pkt);
4744                                 my_rval = TRUE;
4745                         }
4746                 }
4747                 mutex_enter(&sf->sf_mutex);
4748                 if (lip_cnt == sf->sf_lip_cnt) {
4749                         mutex_enter(&target->sft_mutex);
4750                         target->sft_state = old_target_state;
4751                         mutex_exit(&target->sft_mutex);
4752                 }
4753                 mutex_exit(&sf->sf_mutex);
4754         }
4755         return (my_rval);
4756 }
4757 
4758 
4759 /*
4760  * called by the transport and internally to reset a target
4761  */
4762 static int
4763 sf_reset(struct scsi_address *ap, int level)
4764 {
4765         struct scsi_pkt *pkt;
4766         struct fcal_packet *fpkt;
4767         struct sf *sf = ADDR2SF(ap);
4768         struct sf_target *target = ADDR2TARGET(ap), *ntarget;
4769         struct sf_pkt *cmd;
4770         int     rval = FALSE, t;
4771         int     lip_cnt;
4772         int     tgt_id, ret;
4773         fc_frame_header_t       *hp;
4774         int     deferred_destroy;
4775 
4776         /* We don't support RESET_LUN yet. */
4777         if (level == RESET_TARGET) {
4778                 struct sf_reset_list *p;
4779 
4780                 if ((p = kmem_alloc(sizeof (struct sf_reset_list), KM_NOSLEEP))
4781                     == NULL)
4782                         return (rval);
4783 
4784                 SF_DEBUG(2, (sf, CE_NOTE, "sf_reset target\n"));
4785                 mutex_enter(&sf->sf_mutex);
4786                 /* All target resets go to LUN 0 */
4787                 if (target->sft_lun.l) {
4788                         target = sf_lookup_target(sf, target->sft_port_wwn, 0);
4789                 }
4790                 mutex_enter(&target->sft_mutex);
4791                 if (target->sft_state & (SF_TARGET_BUSY |
4792                     SF_TARGET_OFFLINE)) {
4793                         mutex_exit(&target->sft_mutex);
4794                         mutex_exit(&sf->sf_mutex);
4795                         kmem_free(p, sizeof (struct sf_reset_list));
4796                         return (rval);
4797                 }
4798                 lip_cnt = sf->sf_lip_cnt;
4799                 target->sft_state |= SF_TARGET_BUSY;
4800                 for (ntarget = target->sft_next_lun;
4801                     ntarget;
4802                     ntarget = ntarget->sft_next_lun) {
4803                         mutex_enter(&ntarget->sft_mutex);
4804                         /*
4805                          * XXXX If we supported RESET_LUN we should check here
4806                          * to see if any LUN were being reset and somehow fail
4807                          * that operation.
4808                          */
4809                         ntarget->sft_state |= SF_TARGET_BUSY;
4810                         mutex_exit(&ntarget->sft_mutex);
4811                 }
4812                 mutex_exit(&target->sft_mutex);
4813                 mutex_exit(&sf->sf_mutex);
4814 
4815                 deferred_destroy = 0;
4816                 if ((pkt = sf_scsi_init_pkt(ap, NULL, NULL, 0,
4817                     0, 0, 0, NULL, 0)) != NULL) {
4818                         cmd = PKT2CMD(pkt);
4819                         cmd->cmd_block->fcp_cntl.cntl_reset = 1;
4820                         cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
4821                         cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
4822 
4823                         /* prepare the packet for transport */
4824                         if (sf_prepare_pkt(sf, cmd, target) == TRAN_ACCEPT) {
4825                                 /* call transport to send a pkt polled */
4826                                 cmd->cmd_state = SF_STATE_ISSUED;
4827                                 if ((ret = soc_transport_poll(sf->sf_sochandle,
4828                                     cmd->cmd_fp_pkt, SF_ABORT_TIMEOUT,
4829                                     CQ_REQUEST_1)) == FCAL_TRANSPORT_SUCCESS) {
4830                                         (void) ddi_dma_sync(cmd->cmd_cr_pool->
4831                                             rsp_dma_handle, (caddr_t)cmd->
4832                                             cmd_rsp_block - cmd->cmd_cr_pool->
4833                                             rsp_base, FCP_MAX_RSP_IU_SIZE,
4834                                             DDI_DMA_SYNC_FORKERNEL);
4835                                         fpkt = cmd->cmd_fp_pkt;
4836                                         if ((fpkt->fcal_pkt_status ==
4837                                             FCAL_STATUS_OK) &&
4838                                             (((struct fcp_rsp_info *)
4839                                             (&cmd->cmd_rsp_block->
4840                                             fcp_response_len + 1))->
4841                                             rsp_code == FCP_NO_FAILURE)) {
4842                                                 sf_log(sf, CE_NOTE,
4843                                                     "!sf%d: Target 0x%x Reset "
4844                                                     "successful\n",
4845                                                     ddi_get_instance(\
4846                                                     sf->sf_dip),
4847                                                     sf_alpa_to_switch[
4848                                                     target->sft_al_pa]);
4849                                                 rval = TRUE;
4850                                         } else {
4851                                                 hp = &cmd->cmd_fp_pkt->
4852                                                     fcal_socal_request.
4853                                                     sr_fc_frame_hdr;
4854                                                 tgt_id = sf_alpa_to_switch[
4855                                                     (uchar_t)hp->d_id];
4856                                                 sf->sf_stats.tstats[tgt_id].
4857                                                     task_mgmt_failures++;
4858                                                 sf_log(sf, CE_NOTE,
4859                                                     "!sf%d: Target 0x%x "
4860                                                     "Reset failed."
4861                                                     "Status code 0x%x "
4862                                                     "Resp code 0x%x\n",
4863                                                     ddi_get_instance(\
4864                                                     sf->sf_dip),
4865                                                     tgt_id,
4866                                                     fpkt->fcal_pkt_status,
4867                                                     ((struct fcp_rsp_info *)
4868                                                     (&cmd->cmd_rsp_block->
4869                                                     fcp_response_len + 1))->
4870                                                     rsp_code);
4871                                         }
4872                                 } else {
4873                                         sf_log(sf, CE_NOTE, "!sf%d: Target "
4874                                             "0x%x Reset Failed. Ret=%x\n",
4875                                             ddi_get_instance(sf->sf_dip),
4876                                             sf_alpa_to_switch[
4877                                             target->sft_al_pa], ret);
4878                                         mutex_enter(&cmd->cmd_abort_mutex);
4879                                         if (cmd->cmd_state == SF_STATE_ISSUED) {
4880                                         /* call the transport to abort a cmd */
4881                                         cmd->cmd_timeout = sf_watchdog_time
4882                                             + 20;
4883                                         cmd->cmd_state = SF_STATE_ABORTING;
4884                                         mutex_exit(&cmd->cmd_abort_mutex);
4885                                         if (((t = soc_abort(sf->sf_sochandle,
4886                                             sf->sf_socp,
4887                                             sf->sf_sochandle->fcal_portno,
4888                                             cmd->cmd_fp_pkt, 1)) !=
4889                                             FCAL_ABORTED) &&
4890                                             (t != FCAL_ABORT_FAILED)) {
4891                                                 sf_log(sf, CE_NOTE,
4892                                                     "!sf%d: Target 0x%x Reset "
4893                                                     "failed. Abort Failed, "
4894                                                     "forcing LIP\n",
4895                                                     ddi_get_instance(
4896                                                     sf->sf_dip),
4897                                                     sf_alpa_to_switch[
4898                                                     target->sft_al_pa]);
4899                                                 sf_force_lip(sf);
4900                                                 rval = TRUE;
4901                                                 deferred_destroy = 1;
4902                                         }
4903                                         } else {
4904                                                 mutex_exit
4905                                                     (&cmd->cmd_abort_mutex);
4906                                         }
4907                                 }
4908                         }
4909                         /*
4910                          * Defer releasing the packet if we abort returned with
4911                          * a BAD_ABORT or timed out, because there is a
4912                          * possibility that the ucode might return it.
4913                          * We wait for at least 20s and let it be released
4914                          * by the sf_watch thread
4915                          */
4916                         if (!deferred_destroy) {
4917                                 cmd->cmd_block->fcp_cntl.cntl_reset = 0;
4918                                 cmd->cmd_fp_pkt->fcal_pkt_comp =
4919                                     sf_cmd_callback;
4920                                 cmd->cmd_state = SF_STATE_IDLE;
4921                                 /* for cache */
4922                                 sf_scsi_destroy_pkt(ap, pkt);
4923                         }
4924                 } else {
4925                         cmn_err(CE_WARN, "!sf%d: Target 0x%x Reset Failed. "
4926                             "Resource allocation error.\n",
4927                             ddi_get_instance(sf->sf_dip),
4928                             sf_alpa_to_switch[target->sft_al_pa]);
4929                 }
4930                 mutex_enter(&sf->sf_mutex);
4931                 if ((rval == TRUE) && (lip_cnt == sf->sf_lip_cnt)) {
4932                         p->target = target;
4933                         p->lip_cnt = lip_cnt;
4934                         p->timeout = ddi_get_lbolt() +
4935                             drv_usectohz(SF_TARGET_RESET_DELAY);
4936                         p->next = sf->sf_reset_list;
4937                         sf->sf_reset_list = p;
4938                         mutex_exit(&sf->sf_mutex);
4939                         mutex_enter(&sf_global_mutex);
4940                         if (sf_reset_timeout_id == 0) {
4941                                 sf_reset_timeout_id = timeout(
4942                                     sf_check_reset_delay, NULL,
4943                                     drv_usectohz(SF_TARGET_RESET_DELAY));
4944                         }
4945                         mutex_exit(&sf_global_mutex);
4946                 } else {
4947                         if (lip_cnt == sf->sf_lip_cnt) {
4948                                 mutex_enter(&target->sft_mutex);
4949                                 target->sft_state &= ~SF_TARGET_BUSY;
4950                                 for (ntarget = target->sft_next_lun;
4951                                     ntarget;
4952                                     ntarget = ntarget->sft_next_lun) {
4953                                         mutex_enter(&ntarget->sft_mutex);
4954                                         ntarget->sft_state &= ~SF_TARGET_BUSY;
4955                                         mutex_exit(&ntarget->sft_mutex);
4956                                 }
4957                                 mutex_exit(&target->sft_mutex);
4958                         }
4959                         mutex_exit(&sf->sf_mutex);
4960                         kmem_free(p, sizeof (struct sf_reset_list));
4961                 }
4962         } else {
4963                 mutex_enter(&sf->sf_mutex);
4964                 if ((sf->sf_state == SF_STATE_OFFLINE) &&
4965                     (sf_watchdog_time < sf->sf_timer)) {
4966                         /*
4967                          * We are currently in a lip, so let this one
4968                          * finish before forcing another one.
4969                          */
4970                         mutex_exit(&sf->sf_mutex);
4971                         return (TRUE);
4972                 }
4973                 mutex_exit(&sf->sf_mutex);
4974                 sf_log(sf, CE_NOTE, "!sf:Target driver initiated lip\n");
4975                 sf_force_lip(sf);
4976                 rval = TRUE;
4977         }
4978         return (rval);
4979 }
4980 
4981 
4982 /*
4983  * abort all commands for a target
4984  *
4985  * if try_abort is set then send an abort
4986  * if abort is set then this is abort, else this is a reset
4987  */
4988 static void
4989 sf_abort_all(struct sf *sf, struct sf_target *target, int abort, int
4990     lip_cnt, int try_abort)
4991 {
4992         struct sf_target *ntarget;
4993         struct sf_pkt *cmd, *head = NULL, *tail = NULL, *pcmd = NULL, *tcmd;
4994         struct fcal_packet *fpkt;
4995         struct scsi_pkt *pkt;
4996         int rval = FCAL_ABORTED;
4997 
4998         /*
4999          * First pull all commands for all LUNs on this target out of the
5000          * overflow list.  We can tell it's the same target by comparing
5001          * the node WWN.
5002          */
5003         mutex_enter(&sf->sf_mutex);
5004         if (lip_cnt == sf->sf_lip_cnt) {
5005                 mutex_enter(&sf->sf_cmd_mutex);
5006                 cmd = sf->sf_pkt_head;
5007                 while (cmd != NULL) {
5008                         ntarget = ADDR2TARGET(&cmd->cmd_pkt->
5009                             pkt_address);
5010                         if (ntarget == target) {
5011                                 if (pcmd != NULL)
5012                                         pcmd->cmd_next = cmd->cmd_next;
5013                                 else
5014                                         sf->sf_pkt_head = cmd->cmd_next;
5015                                 if (sf->sf_pkt_tail == cmd) {
5016                                         sf->sf_pkt_tail = pcmd;
5017                                         if (pcmd != NULL)
5018                                                 pcmd->cmd_next = NULL;
5019                                 }
5020                                 tcmd = cmd->cmd_next;
5021                                 if (head == NULL) {
5022                                         head = cmd;
5023                                         tail = cmd;
5024                                 } else {
5025                                         tail->cmd_next = cmd;
5026                                         tail = cmd;
5027                                 }
5028                                 cmd->cmd_next = NULL;
5029                                 cmd = tcmd;
5030                         } else {
5031                                 pcmd = cmd;
5032                                 cmd = cmd->cmd_next;
5033                         }
5034                 }
5035                 mutex_exit(&sf->sf_cmd_mutex);
5036         }
5037         mutex_exit(&sf->sf_mutex);
5038 
5039         /*
5040          * Now complete all the commands on our list.  In the process,
5041          * the completion routine may take the commands off the target
5042          * lists.
5043          */
5044         cmd = head;
5045         while (cmd != NULL) {
5046                 pkt = cmd->cmd_pkt;
5047                 if (abort) {
5048                         pkt->pkt_reason = CMD_ABORTED;
5049                         pkt->pkt_statistics |= STAT_ABORTED;
5050                 } else {
5051                         pkt->pkt_reason = CMD_RESET;
5052                         pkt->pkt_statistics |= STAT_DEV_RESET;
5053                 }
5054                 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
5055                 cmd->cmd_state = SF_STATE_IDLE;
5056                 cmd = cmd->cmd_next;
5057                 /*
5058                  * call the packet completion routine only for
5059                  * non-polled commands. Ignore the polled commands as
5060                  * they timeout and will be handled differently
5061                  */
5062                 if ((pkt->pkt_comp) && !(pkt->pkt_flags & FLAG_NOINTR))
5063                         (*pkt->pkt_comp)(pkt);
5064 
5065         }
5066 
5067         /*
5068          * Finally get all outstanding commands for each LUN, and abort them if
5069          * they've been issued, and call the completion routine.
5070          * For the case where sf_offline_target is called from sf_watch
5071          * due to a Offline Timeout, it is quite possible that the soc+
5072          * ucode is hosed and therefore  cannot return the commands.
5073          * Clear up all the issued commands as well.
5074          * Try_abort will be false only if sf_abort_all is coming from
5075          * sf_target_offline.
5076          */
5077 
5078         if (try_abort || sf->sf_state == SF_STATE_OFFLINE) {
5079                 mutex_enter(&target->sft_pkt_mutex);
5080                 cmd = tcmd = target->sft_pkt_head;
5081                 while (cmd != (struct sf_pkt *)&target->sft_pkt_head) {
5082                         fpkt = cmd->cmd_fp_pkt;
5083                         pkt = cmd->cmd_pkt;
5084                         mutex_enter(&cmd->cmd_abort_mutex);
5085                         if ((cmd->cmd_state == SF_STATE_ISSUED) &&
5086                             (fpkt->fcal_cmd_state &
5087                             FCAL_CMD_IN_TRANSPORT) &&
5088                             ((fpkt->fcal_cmd_state & FCAL_CMD_COMPLETE) ==
5089                             0) && !(pkt->pkt_flags & FLAG_NOINTR)) {
5090                                 cmd->cmd_state = SF_STATE_ABORTING;
5091                                 cmd->cmd_timeout = sf_watchdog_time +
5092                                     cmd->cmd_pkt->pkt_time + 20;
5093                                 mutex_exit(&cmd->cmd_abort_mutex);
5094                                 mutex_exit(&target->sft_pkt_mutex);
5095                                 if (try_abort) {
5096                                         /* call the transport to abort a pkt */
5097                                         rval = soc_abort(sf->sf_sochandle,
5098                                             sf->sf_socp,
5099                                             sf->sf_sochandle->fcal_portno,
5100                                             fpkt, 1);
5101                                 }
5102                                 if ((rval == FCAL_ABORTED) ||
5103                                     (rval == FCAL_ABORT_FAILED)) {
5104                                         if (abort) {
5105                                                 pkt->pkt_reason = CMD_ABORTED;
5106                                                 pkt->pkt_statistics |=
5107                                                     STAT_ABORTED;
5108                                         } else {
5109                                                 pkt->pkt_reason = CMD_RESET;
5110                                                 pkt->pkt_statistics |=
5111                                                     STAT_DEV_RESET;
5112                                         }
5113                                         cmd->cmd_state = SF_STATE_IDLE;
5114                                         if (pkt->pkt_comp)
5115                                                 (*pkt->pkt_comp)(pkt);
5116                                 }
5117                                 mutex_enter(&sf->sf_mutex);
5118                                 if (lip_cnt != sf->sf_lip_cnt) {
5119                                         mutex_exit(&sf->sf_mutex);
5120                                         return;
5121                                 }
5122                                 mutex_exit(&sf->sf_mutex);
5123                                 mutex_enter(&target->sft_pkt_mutex);
5124                                 cmd = target->sft_pkt_head;
5125                         } else {
5126                                 mutex_exit(&cmd->cmd_abort_mutex);
5127                                 cmd = cmd->cmd_forw;
5128                         }
5129                 }
5130                 mutex_exit(&target->sft_pkt_mutex);
5131         }
5132 }
5133 
5134 
5135 /*
5136  * called by the transport to start a packet
5137  */
5138 static int
5139 sf_start(struct scsi_address *ap, struct scsi_pkt *pkt)
5140 {
5141         struct sf *sf = ADDR2SF(ap);
5142         struct sf_target *target = ADDR2TARGET(ap);
5143         struct sf_pkt *cmd = PKT2CMD(pkt);
5144         int rval;
5145 
5146 
5147         SF_DEBUG(6, (sf, CE_NOTE, "sf_start\n"));
5148 
5149         if (cmd->cmd_state == SF_STATE_ISSUED) {
5150                 cmn_err(CE_PANIC, "sf: issuing packet twice 0x%p\n",
5151                     (void *)cmd);
5152         }
5153 
5154         /* prepare the packet for transport */
5155         if ((rval = sf_prepare_pkt(sf, cmd, target)) != TRAN_ACCEPT) {
5156                 return (rval);
5157         }
5158 
5159         if (target->sft_state & (SF_TARGET_BUSY|SF_TARGET_OFFLINE)) {
5160                 if (target->sft_state & SF_TARGET_OFFLINE) {
5161                         return (TRAN_FATAL_ERROR);
5162                 }
5163                 if (pkt->pkt_flags & FLAG_NOINTR) {
5164                         return (TRAN_BUSY);
5165                 }
5166                 mutex_enter(&sf->sf_cmd_mutex);
5167                 sf->sf_use_lock = TRUE;
5168                 goto enque;
5169         }
5170 
5171 
5172         /* if no interrupts then do polled I/O */
5173         if (pkt->pkt_flags & FLAG_NOINTR) {
5174                 return (sf_dopoll(sf, cmd));
5175         }
5176 
5177         /* regular interrupt-driven I/O */
5178 
5179         if (!sf->sf_use_lock) {
5180 
5181                 /* locking no needed */
5182 
5183                 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
5184                     sf_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
5185                 cmd->cmd_state = SF_STATE_ISSUED;
5186 
5187                 /* call the transport to send a pkt */
5188                 if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt,
5189                     FCAL_NOSLEEP, CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
5190                         cmd->cmd_state = SF_STATE_IDLE;
5191                         return (TRAN_BADPKT);
5192                 }
5193                 return (TRAN_ACCEPT);
5194         }
5195 
5196         /* regular I/O using locking */
5197 
5198         mutex_enter(&sf->sf_cmd_mutex);
5199         if ((sf->sf_ncmds >= sf->sf_throttle) ||
5200             (sf->sf_pkt_head != NULL)) {
5201 enque:
5202                 /*
5203                  * either we're throttling back or there are already commands
5204                  * on the queue, so enqueue this one for later
5205                  */
5206                 cmd->cmd_flags |= CFLAG_IN_QUEUE;
5207                 if (sf->sf_pkt_head != NULL) {
5208                         /* add to the queue */
5209                         sf->sf_pkt_tail->cmd_next = cmd;
5210                         cmd->cmd_next = NULL;
5211                         sf->sf_pkt_tail = cmd;
5212                 } else {
5213                         /* this is the first entry in the queue */
5214                         sf->sf_pkt_head = sf->sf_pkt_tail = cmd;
5215                         cmd->cmd_next = NULL;
5216                 }
5217                 mutex_exit(&sf->sf_cmd_mutex);
5218                 return (TRAN_ACCEPT);
5219         }
5220 
5221         /*
5222          * start this packet now
5223          */
5224 
5225         /* still have cmd mutex */
5226         return (sf_start_internal(sf, cmd));
5227 }
5228 
5229 
5230 /*
5231  * internal routine to start a packet from the queue now
5232  *
5233  * enter with cmd mutex held and leave with it released
5234  */
5235 static int
5236 sf_start_internal(struct sf *sf, struct sf_pkt *cmd)
5237 {
5238         /* we have the cmd mutex */
5239         sf->sf_ncmds++;
5240         mutex_exit(&sf->sf_cmd_mutex);
5241 
5242         ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
5243         SF_DEBUG(6, (sf, CE_NOTE, "sf_start_internal\n"));
5244 
5245         cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? sf_watchdog_time +
5246             cmd->cmd_pkt->pkt_time : 0;
5247         cmd->cmd_state = SF_STATE_ISSUED;
5248 
5249         /* call transport to send the pkt */
5250         if (soc_transport(sf->sf_sochandle, cmd->cmd_fp_pkt, FCAL_NOSLEEP,
5251             CQ_REQUEST_1) != FCAL_TRANSPORT_SUCCESS) {
5252                 cmd->cmd_state = SF_STATE_IDLE;
5253                 mutex_enter(&sf->sf_cmd_mutex);
5254                 sf->sf_ncmds--;
5255                 mutex_exit(&sf->sf_cmd_mutex);
5256                 return (TRAN_BADPKT);
5257         }
5258         return (TRAN_ACCEPT);
5259 }
5260 
5261 
5262 /*
5263  * prepare a packet for transport
5264  */
5265 static int
5266 sf_prepare_pkt(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target)
5267 {
5268         struct fcp_cmd *fcmd = cmd->cmd_block;
5269 
5270 /* XXXX Need to set the LUN ? */
5271         bcopy((caddr_t)&target->sft_lun.b,
5272             (caddr_t)&fcmd->fcp_ent_addr,
5273             FCP_LUN_SIZE);
5274         cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
5275         cmd->cmd_pkt->pkt_state = 0;
5276         cmd->cmd_pkt->pkt_statistics = 0;
5277 
5278 
5279         if ((cmd->cmd_pkt->pkt_comp == NULL) &&
5280             ((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0)) {
5281                 return (TRAN_BADPKT);
5282         }
5283 
5284         /* invalidate imp field(s) of rsp block */
5285         cmd->cmd_rsp_block->fcp_u.i_fcp_status = SF_BAD_DMA_MAGIC;
5286 
5287         /* set up amt of I/O to do */
5288         if (cmd->cmd_flags & CFLAG_DMAVALID) {
5289                 cmd->cmd_pkt->pkt_resid = cmd->cmd_dmacount;
5290                 if (cmd->cmd_flags & CFLAG_CMDIOPB) {
5291                         (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
5292                             DDI_DMA_SYNC_FORDEV);
5293                 }
5294         } else {
5295                 cmd->cmd_pkt->pkt_resid = 0;
5296         }
5297 
5298         /* set up the Tagged Queuing type */
5299         if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
5300                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
5301         } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
5302                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
5303         }
5304 
5305         /*
5306          * Sync the cmd segment
5307          */
5308         (void) ddi_dma_sync(cmd->cmd_cr_pool->cmd_dma_handle,
5309             (caddr_t)fcmd - cmd->cmd_cr_pool->cmd_base,
5310             sizeof (struct fcp_cmd), DDI_DMA_SYNC_FORDEV);
5311 
5312         sf_fill_ids(sf, cmd, target);
5313         return (TRAN_ACCEPT);
5314 }
5315 
5316 
5317 /*
5318  * fill in packet hdr source and destination IDs and hdr byte count
5319  */
5320 static void
5321 sf_fill_ids(struct sf *sf, struct sf_pkt *cmd, struct sf_target *target)
5322 {
5323         struct fcal_packet *fpkt = cmd->cmd_fp_pkt;
5324         fc_frame_header_t       *hp;
5325 
5326 
5327         hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
5328         hp->d_id = target->sft_al_pa;
5329         hp->s_id = sf->sf_al_pa;
5330         fpkt->fcal_socal_request.sr_soc_hdr.sh_byte_cnt =
5331             cmd->cmd_dmacookie.dmac_size;
5332 }
5333 
5334 
5335 /*
5336  * do polled I/O using transport
5337  */
5338 static int
5339 sf_dopoll(struct sf *sf, struct sf_pkt *cmd)
5340 {
5341         int timeout;
5342         int rval;
5343 
5344 
5345         mutex_enter(&sf->sf_cmd_mutex);
5346         sf->sf_ncmds++;
5347         mutex_exit(&sf->sf_cmd_mutex);
5348 
5349         timeout = cmd->cmd_pkt->pkt_time ? cmd->cmd_pkt->pkt_time
5350             : SF_POLL_TIMEOUT;
5351         cmd->cmd_timeout = 0;
5352         cmd->cmd_fp_pkt->fcal_pkt_comp = NULL;
5353         cmd->cmd_state = SF_STATE_ISSUED;
5354 
5355         /* call transport to send a pkt polled */
5356         rval = soc_transport_poll(sf->sf_sochandle, cmd->cmd_fp_pkt,
5357             timeout*1000000, CQ_REQUEST_1);
5358         mutex_enter(&cmd->cmd_abort_mutex);
5359         cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
5360         if (rval != FCAL_TRANSPORT_SUCCESS) {
5361                 if (rval == FCAL_TRANSPORT_TIMEOUT) {
5362                         cmd->cmd_state = SF_STATE_ABORTING;
5363                         mutex_exit(&cmd->cmd_abort_mutex);
5364                         (void) sf_target_timeout(sf, cmd);
5365                 } else {
5366                         mutex_exit(&cmd->cmd_abort_mutex);
5367                 }
5368                 cmd->cmd_state = SF_STATE_IDLE;
5369                 cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
5370                 mutex_enter(&sf->sf_cmd_mutex);
5371                 sf->sf_ncmds--;
5372                 mutex_exit(&sf->sf_cmd_mutex);
5373                 return (TRAN_BADPKT);
5374         }
5375         mutex_exit(&cmd->cmd_abort_mutex);
5376         cmd->cmd_fp_pkt->fcal_pkt_comp = sf_cmd_callback;
5377         sf_cmd_callback(cmd->cmd_fp_pkt);
5378         return (TRAN_ACCEPT);
5379 }
5380 
5381 
5382 /* a shortcut for defining debug messages below */
5383 #ifdef  DEBUG
5384 #define SF_DMSG1(s)             msg1 = s
5385 #else
5386 #define SF_DMSG1(s)             /* do nothing */
5387 #endif
5388 
5389 
5390 /*
5391  * the pkt_comp callback for command packets
5392  */
5393 static void
5394 sf_cmd_callback(struct fcal_packet *fpkt)
5395 {
5396         struct sf_pkt *cmd = (struct sf_pkt *)fpkt->fcal_pkt_private;
5397         struct scsi_pkt *pkt = cmd->cmd_pkt;
5398         struct sf *sf = ADDR2SF(&pkt->pkt_address);
5399         struct sf_target *target = ADDR2TARGET(&pkt->pkt_address);
5400         struct fcp_rsp *rsp;
5401         char *msg1 = NULL;
5402         char *msg2 = NULL;
5403         short ncmds;
5404         int tgt_id;
5405         int good_scsi_status = TRUE;
5406 
5407 
5408 
5409         if (cmd->cmd_state == SF_STATE_IDLE) {
5410                 cmn_err(CE_PANIC, "sf: completing idle packet 0x%p\n",
5411                     (void *)cmd);
5412         }
5413 
5414         mutex_enter(&cmd->cmd_abort_mutex);
5415         if (cmd->cmd_state == SF_STATE_ABORTING) {
5416                 /* cmd already being aborted -- nothing to do */
5417                 mutex_exit(&cmd->cmd_abort_mutex);
5418                 return;
5419         }
5420 
5421         cmd->cmd_state = SF_STATE_IDLE;
5422         mutex_exit(&cmd->cmd_abort_mutex);
5423 
5424         if (fpkt->fcal_pkt_status == FCAL_STATUS_OK) {
5425 
5426                 (void) ddi_dma_sync(cmd->cmd_cr_pool->rsp_dma_handle,
5427                     (caddr_t)cmd->cmd_rsp_block - cmd->cmd_cr_pool->rsp_base,
5428                     FCP_MAX_RSP_IU_SIZE, DDI_DMA_SYNC_FORKERNEL);
5429 
5430                 rsp = (struct fcp_rsp *)cmd->cmd_rsp_block;
5431 
5432                 if (rsp->fcp_u.i_fcp_status == SF_BAD_DMA_MAGIC) {
5433 
5434                         if (sf_core && (sf_core & SF_CORE_BAD_DMA)) {
5435                                 sf_token = (int *)(uintptr_t)
5436                                     fpkt->fcal_socal_request.\
5437                                     sr_soc_hdr.sh_request_token;
5438                                 (void) soc_take_core(sf->sf_sochandle,
5439                                     sf->sf_socp);
5440                         }
5441 
5442                         pkt->pkt_reason = CMD_INCOMPLETE;
5443                         pkt->pkt_state = STATE_GOT_BUS;
5444                         pkt->pkt_statistics |= STAT_ABORTED;
5445 
5446                 } else {
5447 
5448                         pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
5449                             STATE_SENT_CMD | STATE_GOT_STATUS;
5450                         pkt->pkt_resid = 0;
5451                         if (cmd->cmd_flags & CFLAG_DMAVALID) {
5452                                 pkt->pkt_state |= STATE_XFERRED_DATA;
5453                         }
5454 
5455                         if ((pkt->pkt_scbp != NULL) &&
5456                             ((*(pkt->pkt_scbp) =
5457                             rsp->fcp_u.fcp_status.scsi_status)
5458                             != STATUS_GOOD)) {
5459                                 good_scsi_status = FALSE;
5460                         /*
5461                          * The next two checks make sure that if there
5462                          * is no sense data or a valid response and
5463                          * the command came back with check condition,
5464                          * the command should be retried
5465                          */
5466                                 if (!rsp->fcp_u.fcp_status.rsp_len_set &&
5467                                     !rsp->fcp_u.fcp_status.sense_len_set) {
5468                                         pkt->pkt_state &= ~STATE_XFERRED_DATA;
5469                                         pkt->pkt_resid = cmd->cmd_dmacount;
5470                                 }
5471                         }
5472 
5473                         if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
5474                             (pkt->pkt_state & STATE_XFERRED_DATA)) {
5475                                 (void) ddi_dma_sync(cmd->cmd_dmahandle, 0,
5476                                     (uint_t)0, DDI_DMA_SYNC_FORCPU);
5477                         }
5478                         /*
5479                          * Update the transfer resid, if appropriate
5480                          */
5481                         if (rsp->fcp_u.fcp_status.resid_over ||
5482                             rsp->fcp_u.fcp_status.resid_under)
5483                                 pkt->pkt_resid = rsp->fcp_resid;
5484 
5485                         /*
5486                          * Check to see if the SCSI command failed.
5487                          *
5488                          */
5489 
5490                         /*
5491                          * First see if we got a FCP protocol error.
5492                          */
5493                         if (rsp->fcp_u.fcp_status.rsp_len_set) {
5494                                 struct fcp_rsp_info *bep;
5495 
5496                                 bep = (struct fcp_rsp_info *)
5497                                     (&rsp->fcp_response_len + 1);
5498                                 if (bep->rsp_code != FCP_NO_FAILURE) {
5499                                                 pkt->pkt_reason = CMD_TRAN_ERR;
5500                                         tgt_id = pkt->pkt_address.a_target;
5501                                         switch (bep->rsp_code) {
5502                                         case FCP_CMND_INVALID:
5503                                                 SF_DMSG1("FCP_RSP FCP_CMND "
5504                                                     "fields invalid");
5505                                                 break;
5506                                         case FCP_TASK_MGMT_NOT_SUPPTD:
5507                                                 SF_DMSG1("FCP_RSP Task"
5508                                                     "Management Function"
5509                                                     "Not Supported");
5510                                                 break;
5511                                         case FCP_TASK_MGMT_FAILED:
5512                                                 SF_DMSG1("FCP_RSP Task "
5513                                                     "Management Function"
5514                                                     "Failed");
5515                                                 sf->sf_stats.tstats[tgt_id].
5516                                                     task_mgmt_failures++;
5517                                                 break;
5518                                         case FCP_DATA_RO_MISMATCH:
5519                                                 SF_DMSG1("FCP_RSP FCP_DATA RO "
5520                                                     "mismatch with "
5521                                                     "FCP_XFER_RDY DATA_RO");
5522                                                 sf->sf_stats.tstats[tgt_id].
5523                                                     data_ro_mismatches++;
5524                                                 break;
5525                                         case FCP_DL_LEN_MISMATCH:
5526                                                 SF_DMSG1("FCP_RSP FCP_DATA "
5527                                                     "length "
5528                                                     "different than BURST_LEN");
5529                                                 sf->sf_stats.tstats[tgt_id].
5530                                                     dl_len_mismatches++;
5531                                                 break;
5532                                         default:
5533                                                 SF_DMSG1("FCP_RSP invalid "
5534                                                     "RSP_CODE");
5535                                                 break;
5536                                         }
5537                                 }
5538                         }
5539 
5540                         /*
5541                          * See if we got a SCSI error with sense data
5542                          */
5543                         if (rsp->fcp_u.fcp_status.sense_len_set) {
5544                                 uchar_t rqlen = min(rsp->fcp_sense_len,
5545                                     sizeof (struct scsi_extended_sense));
5546                                 caddr_t sense = (caddr_t)rsp +
5547                                     sizeof (struct fcp_rsp) +
5548                                     rsp->fcp_response_len;
5549                                 struct scsi_arq_status *arq;
5550                                 struct scsi_extended_sense *sensep =
5551                                     (struct scsi_extended_sense *)sense;
5552 
5553                                 if (rsp->fcp_u.fcp_status.scsi_status !=
5554                                     STATUS_GOOD) {
5555                                 if (rsp->fcp_u.fcp_status.scsi_status
5556                                     == STATUS_CHECK) {
5557                                         if (sensep->es_key ==
5558                                             KEY_RECOVERABLE_ERROR)
5559                                                 good_scsi_status = 1;
5560                                         if (sensep->es_key ==
5561                                             KEY_UNIT_ATTENTION &&
5562                                             sensep->es_add_code == 0x3f &&
5563                                             sensep->es_qual_code == 0x0e) {
5564                                                 /* REPORT_LUNS_HAS_CHANGED */
5565                                                 sf_log(sf, CE_NOTE,
5566                                                 "!REPORT_LUNS_HAS_CHANGED\n");
5567                                                 sf_force_lip(sf);
5568                                         }
5569                                 }
5570                                 }
5571 
5572                                 if ((pkt->pkt_scbp != NULL) &&
5573                                     (cmd->cmd_scblen >=
5574                                         sizeof (struct scsi_arq_status))) {
5575 
5576                                 pkt->pkt_state |= STATE_ARQ_DONE;
5577 
5578                                 arq = (struct scsi_arq_status *)pkt->pkt_scbp;
5579                                 /*
5580                                  * copy out sense information
5581                                  */
5582                                 bcopy(sense, (caddr_t)&arq->sts_sensedata,
5583                                     rqlen);
5584                                 arq->sts_rqpkt_resid =
5585                                     sizeof (struct scsi_extended_sense) -
5586                                         rqlen;
5587                                 *((uchar_t *)&arq->sts_rqpkt_status) =
5588                                     STATUS_GOOD;
5589                                 arq->sts_rqpkt_reason = 0;
5590                                 arq->sts_rqpkt_statistics = 0;
5591                                 arq->sts_rqpkt_state = STATE_GOT_BUS |
5592                                     STATE_GOT_TARGET | STATE_SENT_CMD |
5593                                     STATE_GOT_STATUS | STATE_ARQ_DONE |
5594                                     STATE_XFERRED_DATA;
5595                             }
5596                                 target->sft_alive = TRUE;
5597                         }
5598 
5599                         /*
5600                          * The firmware returns the number of bytes actually
5601                          * xfered into/out of host. Compare this with what
5602                          * we asked and if it is different, we lost frames ?
5603                          */
5604                         if ((pkt->pkt_reason == 0) && (pkt->pkt_resid == 0) &&
5605                             (good_scsi_status) &&
5606                             (pkt->pkt_state & STATE_XFERRED_DATA) &&
5607                             (!(cmd->cmd_flags & CFLAG_CMDIOPB)) &&
5608                             (target->sft_device_type != DTYPE_ESI)) {
5609                                 int byte_cnt =
5610                                     fpkt->fcal_socal_request.
5611                                     sr_soc_hdr.sh_byte_cnt;
5612                                 if (cmd->cmd_flags & CFLAG_DMASEND) {
5613                                         if (byte_cnt != 0) {
5614                                         sf_log(sf, CE_NOTE,
5615                                             "!sf_cmd_callback: Lost Frame: "
5616                                             "(write) received 0x%x expected"
5617                                             " 0x%x target 0x%x\n",
5618                                             byte_cnt, cmd->cmd_dmacount,
5619                                             sf_alpa_to_switch[
5620                                             target->sft_al_pa]);
5621                                         pkt->pkt_reason = CMD_INCOMPLETE;
5622                                         pkt->pkt_statistics |= STAT_ABORTED;
5623                                         }
5624                                 } else if (byte_cnt < cmd->cmd_dmacount) {
5625                                         sf_log(sf, CE_NOTE,
5626                                             "!sf_cmd_callback: "
5627                                             "Lost Frame: (read) "
5628                                             "received 0x%x expected 0x%x "
5629                                             "target 0x%x\n", byte_cnt,
5630                                             cmd->cmd_dmacount,
5631                                             sf_alpa_to_switch[
5632                                             target->sft_al_pa]);
5633                                         pkt->pkt_reason = CMD_INCOMPLETE;
5634                                         pkt->pkt_statistics |= STAT_ABORTED;
5635                                 }
5636                         }
5637                 }
5638 
5639         } else {
5640 
5641                 /* pkt status was not ok */
5642 
5643                 switch (fpkt->fcal_pkt_status) {
5644 
5645                 case FCAL_STATUS_ERR_OFFLINE:
5646                         SF_DMSG1("Fibre Channel Offline");
5647                         mutex_enter(&target->sft_mutex);
5648                         if (!(target->sft_state & SF_TARGET_OFFLINE)) {
5649                                 target->sft_state |= (SF_TARGET_BUSY
5650                                     | SF_TARGET_MARK);
5651                         }
5652                         mutex_exit(&target->sft_mutex);
5653                         (void) ndi_event_retrieve_cookie(sf->sf_event_hdl,
5654                             target->sft_dip, FCAL_REMOVE_EVENT,
5655                             &sf_remove_eid, NDI_EVENT_NOPASS);
5656                         (void) ndi_event_run_callbacks(sf->sf_event_hdl,
5657                             target->sft_dip, sf_remove_eid, NULL);
5658                         pkt->pkt_reason = CMD_TRAN_ERR;
5659                         pkt->pkt_statistics |= STAT_BUS_RESET;
5660                         break;
5661 
5662                 case FCAL_STATUS_MAX_XCHG_EXCEEDED:
5663                         sf_throttle(sf);
5664                         sf->sf_use_lock = TRUE;
5665                         pkt->pkt_reason = CMD_TRAN_ERR;
5666                         pkt->pkt_state = STATE_GOT_BUS;
5667                         pkt->pkt_statistics |= STAT_ABORTED;
5668                         break;
5669 
5670                 case FCAL_STATUS_TIMEOUT:
5671                         SF_DMSG1("Fibre Channel Timeout");
5672                         pkt->pkt_reason = CMD_TIMEOUT;
5673                         break;
5674 
5675                 case FCAL_STATUS_ERR_OVERRUN:
5676                         SF_DMSG1("CMD_DATA_OVR");
5677                         pkt->pkt_reason = CMD_DATA_OVR;
5678                         break;
5679 
5680                 case FCAL_STATUS_UNKNOWN_CQ_TYPE:
5681                         SF_DMSG1("Unknown CQ type");
5682                         pkt->pkt_reason = CMD_TRAN_ERR;
5683                         break;
5684 
5685                 case FCAL_STATUS_BAD_SEG_CNT:
5686                         SF_DMSG1("Bad SEG CNT");
5687                         pkt->pkt_reason = CMD_TRAN_ERR;
5688                         break;
5689 
5690                 case FCAL_STATUS_BAD_XID:
5691                         SF_DMSG1("Fibre Channel Invalid X_ID");
5692                         pkt->pkt_reason = CMD_TRAN_ERR;
5693                         break;
5694 
5695                 case FCAL_STATUS_XCHG_BUSY:
5696                         SF_DMSG1("Fibre Channel Exchange Busy");
5697                         pkt->pkt_reason = CMD_TRAN_ERR;
5698                         break;
5699 
5700                 case FCAL_STATUS_INSUFFICIENT_CQES:
5701                         SF_DMSG1("Insufficient CQEs");
5702                         pkt->pkt_reason = CMD_TRAN_ERR;
5703                         break;
5704 
5705                 case FCAL_STATUS_ALLOC_FAIL:
5706                         SF_DMSG1("ALLOC FAIL");
5707                         pkt->pkt_reason = CMD_TRAN_ERR;
5708                         break;
5709 
5710                 case FCAL_STATUS_BAD_SID:
5711                         SF_DMSG1("Fibre Channel Invalid S_ID");
5712                         pkt->pkt_reason = CMD_TRAN_ERR;
5713                         break;
5714 
5715                 case FCAL_STATUS_INCOMPLETE_DMA_ERR:
5716                         if (sf_core && (sf_core & SF_CORE_INCOMPLETE_DMA)) {
5717                                 sf_token = (int *)(uintptr_t)
5718                                     fpkt->fcal_socal_request.\
5719                                     sr_soc_hdr.sh_request_token;
5720                                 (void) soc_take_core(sf->sf_sochandle,
5721                                     sf->sf_socp);
5722                                 sf_core = 0;
5723                         }
5724                         msg2 =
5725                         "INCOMPLETE DMA XFER due to bad SOC+ card, replace HBA";
5726                         pkt->pkt_reason = CMD_INCOMPLETE;
5727                         pkt->pkt_state = STATE_GOT_BUS;
5728                         pkt->pkt_statistics |= STAT_ABORTED;
5729                         break;
5730 
5731                 case FCAL_STATUS_CRC_ERR:
5732                         msg2 = "Fibre Channel CRC Error on frames";
5733                         pkt->pkt_reason = CMD_INCOMPLETE;
5734                         pkt->pkt_state = STATE_GOT_BUS;
5735                         pkt->pkt_statistics |= STAT_ABORTED;
5736                         break;
5737 
5738                 case FCAL_STATUS_NO_SEQ_INIT:
5739                         SF_DMSG1("Fibre Channel Seq Init Error");
5740                         pkt->pkt_reason = CMD_TRAN_ERR;
5741                         break;
5742 
5743                 case  FCAL_STATUS_OPEN_FAIL:
5744                         pkt->pkt_reason = CMD_TRAN_ERR;
5745                         SF_DMSG1("Fibre Channel Open Failure");
5746                         if ((target->sft_state & (SF_TARGET_BUSY |
5747                             SF_TARGET_MARK | SF_TARGET_OFFLINE)) == 0) {
5748                                 sf_log(sf, CE_NOTE,
5749                                     "!Open failure to target 0x%x "
5750                                     "forcing LIP\n",
5751                                     sf_alpa_to_switch[target->sft_al_pa]);
5752                                 sf_force_lip(sf);
5753                         }
5754                         break;
5755 
5756 
5757                 case FCAL_STATUS_ONLINE_TIMEOUT:
5758                         SF_DMSG1("Fibre Channel Online Timeout");
5759                         pkt->pkt_reason = CMD_TRAN_ERR;
5760                         break;
5761 
5762                 default:
5763                         SF_DMSG1("Unknown FC Status");
5764                         pkt->pkt_reason = CMD_TRAN_ERR;
5765                         break;
5766                 }
5767         }
5768 
5769 #ifdef  DEBUG
5770         /*
5771          * msg1 will be non-NULL if we've detected some sort of error
5772          */
5773         if (msg1 != NULL && sfdebug >= 4) {
5774                 sf_log(sf, CE_WARN,
5775                     "!Transport error on cmd=0x%p target=0x%x:  %s\n",
5776                     (void *)fpkt, pkt->pkt_address.a_target, msg1);
5777         }
5778 #endif
5779 
5780         if (msg2 != NULL) {
5781                 sf_log(sf, CE_WARN, "!Transport error on target=0x%x:  %s\n",
5782                     pkt->pkt_address.a_target, msg2);
5783         }
5784 
5785         ncmds = fpkt->fcal_ncmds;
5786         ASSERT(ncmds >= 0);
5787         if (ncmds >= (sf->sf_throttle - SF_HI_CMD_DELTA)) {
5788 #ifdef DEBUG
5789                 if (!sf->sf_use_lock) {
5790                         SF_DEBUG(4, (sf, CE_NOTE, "use lock flag on\n"));
5791                 }
5792 #endif
5793                 sf->sf_use_lock = TRUE;
5794         }
5795 
5796         mutex_enter(&sf->sf_cmd_mutex);
5797         sf->sf_ncmds = ncmds;
5798         sf_throttle_start(sf);
5799         mutex_exit(&sf->sf_cmd_mutex);
5800 
5801         if (!msg1 && !msg2)
5802                 SF_DEBUG(6, (sf, CE_NOTE, "Completing pkt 0x%p\n",
5803                     (void *)pkt));
5804         if (pkt->pkt_comp != NULL) {
5805                 (*pkt->pkt_comp)(pkt);
5806         }
5807 }
5808 
5809 #undef  SF_DMSG1
5810 
5811 
5812 
5813 /*
5814  * start throttling for this instance
5815  */
5816 static void
5817 sf_throttle_start(struct sf *sf)
5818 {
5819         struct sf_pkt *cmd, *prev_cmd = NULL;
5820         struct scsi_pkt *pkt;
5821         struct sf_target *target;
5822 
5823 
5824         ASSERT(mutex_owned(&sf->sf_cmd_mutex));
5825 
5826         cmd = sf->sf_pkt_head;
5827         while ((cmd != NULL) &&
5828             (sf->sf_state == SF_STATE_ONLINE) &&
5829             (sf->sf_ncmds < sf->sf_throttle)) {
5830 
5831                 pkt = CMD2PKT(cmd);
5832 
5833                 target = ADDR2TARGET(&pkt->pkt_address);
5834                 if (target->sft_state & SF_TARGET_BUSY) {
5835                         /* this command is busy -- go to next */
5836                         ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
5837                         prev_cmd = cmd;
5838                         cmd = cmd->cmd_next;
5839                         continue;
5840                 }
5841 
5842                 ASSERT(cmd->cmd_state != SF_STATE_ISSUED);
5843 
5844                 /* this cmd not busy and not issued */
5845 
5846                 /* remove this packet from the queue */
5847                 if (sf->sf_pkt_head == cmd) {
5848                         /* this was the first packet */
5849                         sf->sf_pkt_head = cmd->cmd_next;
5850                 } else if (sf->sf_pkt_tail == cmd) {
5851                         /* this was the last packet */
5852                         sf->sf_pkt_tail = prev_cmd;
5853                         if (prev_cmd != NULL) {
5854                                 prev_cmd->cmd_next = NULL;
5855                         }
5856                 } else {
5857                         /* some packet in the middle of the queue */
5858                         ASSERT(prev_cmd != NULL);
5859                         prev_cmd->cmd_next = cmd->cmd_next;
5860                 }
5861                 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
5862 
5863                 if (target->sft_state & SF_TARGET_OFFLINE) {
5864                         mutex_exit(&sf->sf_cmd_mutex);
5865                         pkt->pkt_reason = CMD_TRAN_ERR;
5866                         if (pkt->pkt_comp != NULL) {
5867                                 (*pkt->pkt_comp)(cmd->cmd_pkt);
5868                         }
5869                 } else {
5870                         sf_fill_ids(sf, cmd, target);
5871                         if (sf_start_internal(sf, cmd) != TRAN_ACCEPT) {
5872                                 pkt->pkt_reason = CMD_TRAN_ERR;
5873                                 if (pkt->pkt_comp != NULL) {
5874                                         (*pkt->pkt_comp)(cmd->cmd_pkt);
5875                                 }
5876                         }
5877                 }
5878                 mutex_enter(&sf->sf_cmd_mutex);
5879                 cmd = sf->sf_pkt_head;
5880                 prev_cmd = NULL;
5881         }
5882 }
5883 
5884 
5885 /*
5886  * called when the max exchange value is exceeded to throttle back commands
5887  */
5888 static void
5889 sf_throttle(struct sf *sf)
5890 {
5891         int cmdmax = sf->sf_sochandle->fcal_cmdmax;
5892 
5893 
5894         mutex_enter(&sf->sf_cmd_mutex);
5895 
5896         sf->sf_flag = TRUE;
5897 
5898         if (sf->sf_ncmds > (cmdmax / 2)) {
5899                 sf->sf_throttle = cmdmax / 2;
5900         } else {
5901                 if (sf->sf_ncmds > SF_DECR_DELTA) {
5902                         sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA;
5903                 } else {
5904                         /*
5905                          * This case is just a safeguard, should not really
5906                          * happen(ncmds < SF_DECR_DELTA and MAX_EXCHG exceed
5907                          */
5908                         sf->sf_throttle = SF_DECR_DELTA;
5909                 }
5910         }
5911         mutex_exit(&sf->sf_cmd_mutex);
5912 
5913         sf = sf->sf_sibling;
5914         if (sf != NULL) {
5915                 mutex_enter(&sf->sf_cmd_mutex);
5916                 sf->sf_flag = TRUE;
5917                 if (sf->sf_ncmds >= (cmdmax / 2)) {
5918                         sf->sf_throttle = cmdmax / 2;
5919                 } else {
5920                         if (sf->sf_ncmds > SF_DECR_DELTA) {
5921                                 sf->sf_throttle = sf->sf_ncmds - SF_DECR_DELTA;
5922                         } else {
5923                                 sf->sf_throttle = SF_DECR_DELTA;
5924                         }
5925                 }
5926 
5927                 mutex_exit(&sf->sf_cmd_mutex);
5928         }
5929 }
5930 
5931 
5932 /*
5933  * sf watchdog routine, called for a timeout
5934  */
5935 /*ARGSUSED*/
5936 static void
5937 sf_watch(void *arg)
5938 {
5939         struct sf *sf;
5940         struct sf_els_hdr       *privp;
5941         static int count = 0, pscan_count = 0;
5942         int cmdmax, i, mescount = 0;
5943         struct sf_target *target;
5944 
5945 
5946         sf_watchdog_time += sf_watchdog_timeout;
5947         count++;
5948         pscan_count++;
5949 
5950         mutex_enter(&sf_global_mutex);
5951         sf_watch_running = 1;
5952         for (sf = sf_head; sf != NULL; sf = sf->sf_next) {
5953 
5954                 mutex_exit(&sf_global_mutex);
5955 
5956                 /* disable throttling while we're suspended */
5957                 mutex_enter(&sf->sf_mutex);
5958                 if (sf->sf_state & SF_STATE_SUSPENDED) {
5959                         mutex_exit(&sf->sf_mutex);
5960                         SF_DEBUG(1, (sf, CE_CONT,
5961                             "sf_watch, sf%d:throttle disabled "
5962                             "due to DDI_SUSPEND\n",
5963                             ddi_get_instance(sf->sf_dip)));
5964                         mutex_enter(&sf_global_mutex);
5965                         continue;
5966                 }
5967                 mutex_exit(&sf->sf_mutex);
5968 
5969                 cmdmax = sf->sf_sochandle->fcal_cmdmax;
5970 
5971                 if (sf->sf_take_core) {
5972                         (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
5973                 }
5974 
5975                 mutex_enter(&sf->sf_cmd_mutex);
5976 
5977                 if (!sf->sf_flag) {
5978                         if (sf->sf_throttle < (cmdmax / 2)) {
5979                                 sf->sf_throttle = cmdmax / 2;
5980                         } else if ((sf->sf_throttle += SF_INCR_DELTA) >
5981                             cmdmax) {
5982                                 sf->sf_throttle = cmdmax;
5983                         }
5984                 } else {
5985                         sf->sf_flag = FALSE;
5986                 }
5987 
5988                 sf->sf_ncmds_exp_avg = (sf->sf_ncmds + sf->sf_ncmds_exp_avg)
5989                     >> 2;
5990                 if ((sf->sf_ncmds <= (sf->sf_throttle - SF_LO_CMD_DELTA)) &&
5991                     (sf->sf_pkt_head == NULL)) {
5992 #ifdef DEBUG
5993                         if (sf->sf_use_lock) {
5994                                 SF_DEBUG(4, (sf, CE_NOTE,
5995                                     "use lock flag off\n"));
5996                         }
5997 #endif
5998                         sf->sf_use_lock = FALSE;
5999                 }
6000 
6001                 if (sf->sf_state == SF_STATE_ONLINE && sf->sf_pkt_head &&
6002                     sf->sf_ncmds < sf->sf_throttle) {
6003                         sf_throttle_start(sf);
6004                 }
6005 
6006                 mutex_exit(&sf->sf_cmd_mutex);
6007 
6008                 if (pscan_count >= sf_pool_scan_cnt) {
6009                         if (sf->sf_ncmds_exp_avg < (sf->sf_cr_pool_cnt <<
6010                             SF_LOG2_ELEMS_IN_POOL) - SF_FREE_CR_EPSILON) {
6011                                 sf_crpool_free(sf);
6012                         }
6013                 }
6014                 mutex_enter(&sf->sf_mutex);
6015 
6016                 privp = sf->sf_els_list;
6017                 while (privp != NULL) {
6018                         if (privp->timeout < sf_watchdog_time) {
6019                                 /* timeout this command */
6020                                 privp = sf_els_timeout(sf, privp);
6021                         } else if ((privp->timeout == SF_INVALID_TIMEOUT) &&
6022                             (privp->lip_cnt != sf->sf_lip_cnt)) {
6023                                 if (privp->prev != NULL) {
6024                                         privp->prev->next = privp->next;
6025                                 }
6026                                 if (sf->sf_els_list == privp) {
6027                                         sf->sf_els_list = privp->next;
6028                                 }
6029                                 if (privp->next != NULL) {
6030                                         privp->next->prev = privp->prev;
6031                                 }
6032                                 mutex_exit(&sf->sf_mutex);
6033                                 sf_els_free(privp->fpkt);
6034                                 mutex_enter(&sf->sf_mutex);
6035                                 privp = sf->sf_els_list;
6036                         } else {
6037                                 privp = privp->next;
6038                         }
6039                 }
6040 
6041                 if (sf->sf_online_timer && sf->sf_online_timer <
6042                     sf_watchdog_time) {
6043                         for (i = 0; i < sf_max_targets; i++) {
6044                                 target = sf->sf_targets[i];
6045                                 if (target != NULL) {
6046                                         if (!mescount && target->sft_state &
6047                                             SF_TARGET_BUSY) {
6048                                                 sf_log(sf, CE_WARN, "!Loop "
6049                                                     "Unstable: Failed to bring "
6050                                                     "Loop Online\n");
6051                                                 mescount = 1;
6052                                         }
6053                                         target->sft_state |= SF_TARGET_MARK;
6054                                 }
6055                         }
6056                         sf_finish_init(sf, sf->sf_lip_cnt);
6057                         sf->sf_state = SF_STATE_INIT;
6058                         sf->sf_online_timer = 0;
6059                 }
6060 
6061                 if (sf->sf_state == SF_STATE_ONLINE) {
6062                         mutex_exit(&sf->sf_mutex);
6063                         if (count >= sf_pkt_scan_cnt) {
6064                                 sf_check_targets(sf);
6065                         }
6066                 } else if ((sf->sf_state == SF_STATE_OFFLINE) &&
6067                     (sf->sf_timer < sf_watchdog_time)) {
6068                         for (i = 0; i < sf_max_targets; i++) {
6069                                 target = sf->sf_targets[i];
6070                                 if ((target != NULL) &&
6071                                     (target->sft_state &
6072                                     SF_TARGET_BUSY)) {
6073                                         sf_log(sf, CE_WARN,
6074                                             "!Offline Timeout\n");
6075                                         if (sf_core && (sf_core &
6076                                             SF_CORE_OFFLINE_TIMEOUT)) {
6077                                                 (void) soc_take_core(
6078                                                     sf->sf_sochandle,
6079                                                     sf->sf_socp);
6080                                                 sf_core = 0;
6081                                         }
6082                                         break;
6083                                 }
6084                         }
6085                         sf_finish_init(sf, sf->sf_lip_cnt);
6086                         sf->sf_state = SF_STATE_INIT;
6087                         mutex_exit(&sf->sf_mutex);
6088                 } else {
6089                         mutex_exit(&sf->sf_mutex);
6090                 }
6091                 mutex_enter(&sf_global_mutex);
6092         }
6093         mutex_exit(&sf_global_mutex);
6094         if (count >= sf_pkt_scan_cnt) {
6095                 count = 0;
6096         }
6097         if (pscan_count >= sf_pool_scan_cnt) {
6098                 pscan_count = 0;
6099         }
6100 
6101         /* reset timeout */
6102         sf_watchdog_id = timeout(sf_watch, (caddr_t)0, sf_watchdog_tick);
6103 
6104         /* signal waiting thread */
6105         mutex_enter(&sf_global_mutex);
6106         sf_watch_running = 0;
6107         cv_broadcast(&sf_watch_cv);
6108         mutex_exit(&sf_global_mutex);
6109 }
6110 
6111 
6112 /*
6113  * called during a timeout to check targets
6114  */
6115 static void
6116 sf_check_targets(struct sf *sf)
6117 {
6118         struct sf_target *target;
6119         int i;
6120         struct sf_pkt *cmd;
6121         struct scsi_pkt *pkt;
6122         int lip_cnt;
6123 
6124         mutex_enter(&sf->sf_mutex);
6125         lip_cnt = sf->sf_lip_cnt;
6126         mutex_exit(&sf->sf_mutex);
6127 
6128         /* check scan all possible targets */
6129         for (i = 0; i < sf_max_targets; i++) {
6130                 target = sf->sf_targets[i];
6131                 while (target != NULL) {
6132                         mutex_enter(&target->sft_pkt_mutex);
6133                         if (target->sft_alive && target->sft_scan_count !=
6134                             sf_target_scan_cnt) {
6135                                 target->sft_alive = 0;
6136                                 target->sft_scan_count++;
6137                                 mutex_exit(&target->sft_pkt_mutex);
6138                                 return;
6139                         }
6140                         target->sft_alive = 0;
6141                         target->sft_scan_count = 0;
6142                         cmd = target->sft_pkt_head;
6143                         while (cmd != (struct sf_pkt *)&target->sft_pkt_head) {
6144                                 mutex_enter(&cmd->cmd_abort_mutex);
6145                                 if (cmd->cmd_state == SF_STATE_ISSUED &&
6146                                     ((cmd->cmd_timeout && sf_watchdog_time >
6147 #ifdef  DEBUG
6148                                     cmd->cmd_timeout) || sf_abort_flag)) {
6149                                         sf_abort_flag = 0;
6150 #else
6151                                         cmd->cmd_timeout))) {
6152 #endif
6153                                         cmd->cmd_timeout = 0;
6154         /* prevent reset from getting at this packet */
6155                                         cmd->cmd_state = SF_STATE_ABORTING;
6156                                         mutex_exit(&cmd->cmd_abort_mutex);
6157                                         mutex_exit(&target->sft_pkt_mutex);
6158                                         sf->sf_stats.tstats[i].timeouts++;
6159                                         if (sf_target_timeout(sf, cmd))
6160                                                 return;
6161                                         else {
6162                                                 if (lip_cnt != sf->sf_lip_cnt) {
6163                                                         return;
6164                                                 } else {
6165                                                         mutex_enter(&target->
6166                                                             sft_pkt_mutex);
6167                                                         cmd = target->
6168                                                             sft_pkt_head;
6169                                                 }
6170                                         }
6171         /*
6172          * if the abort and lip fail, a reset will be carried out.
6173          * But the reset will ignore this packet. We have waited at least
6174          * 20 seconds after the initial timeout. Now, complete it here.
6175          * This also takes care of spurious bad aborts.
6176          */
6177                                 } else if ((cmd->cmd_state ==
6178                                     SF_STATE_ABORTING) && (cmd->cmd_timeout
6179                                     <= sf_watchdog_time)) {
6180                                         cmd->cmd_state = SF_STATE_IDLE;
6181                                         mutex_exit(&cmd->cmd_abort_mutex);
6182                                         mutex_exit(&target->sft_pkt_mutex);
6183                                         SF_DEBUG(1, (sf, CE_NOTE,
6184                                             "Command 0x%p to sft 0x%p"
6185                                             " delayed release\n",
6186                                             (void *)cmd, (void *)target));
6187                                         pkt = cmd->cmd_pkt;
6188                                         pkt->pkt_statistics |=
6189                                             (STAT_TIMEOUT|STAT_ABORTED);
6190                                         pkt->pkt_reason = CMD_TIMEOUT;
6191                                         if (pkt->pkt_comp) {
6192                                                 scsi_hba_pkt_comp(pkt);
6193                                         /* handle deferred_destroy case */
6194                                         } else {
6195                                                 if ((cmd->cmd_block->fcp_cntl.
6196                                                     cntl_reset == 1) ||
6197                                                     (cmd->cmd_block->
6198                                                     fcp_cntl.cntl_abort_tsk ==
6199                                                     1)) {
6200                                                         cmd->cmd_block->
6201                                                             fcp_cntl.
6202                                                             cntl_reset = 0;
6203                                                         cmd->cmd_block->
6204                                                             fcp_cntl.
6205                                                             cntl_abort_tsk = 0;
6206                                                         cmd->cmd_fp_pkt->
6207                                                             fcal_pkt_comp =
6208                                                             sf_cmd_callback;
6209                                                         /* for cache */
6210                                                         sf_scsi_destroy_pkt
6211                                                             (&pkt->pkt_address,
6212                                                             pkt);
6213                                                 }
6214                                         }
6215                                         mutex_enter(&target->sft_pkt_mutex);
6216                                         cmd = target->sft_pkt_head;
6217                                 } else {
6218                                         mutex_exit(&cmd->cmd_abort_mutex);
6219                                         cmd = cmd->cmd_forw;
6220                                 }
6221                         }
6222                         mutex_exit(&target->sft_pkt_mutex);
6223                         target = target->sft_next_lun;
6224                 }
6225         }
6226 }
6227 
6228 
6229 /*
6230  * a command to a target has timed out
6231  * return TRUE iff cmd abort failed or timed out, else return FALSE
6232  */
6233 static int
6234 sf_target_timeout(struct sf *sf, struct sf_pkt *cmd)
6235 {
6236         int rval;
6237         struct scsi_pkt *pkt;
6238         struct fcal_packet *fpkt;
6239         int tgt_id;
6240         int retval = FALSE;
6241 
6242 
6243         SF_DEBUG(1, (sf, CE_NOTE, "Command 0x%p to target %x timed out\n",
6244             (void *)cmd->cmd_fp_pkt, cmd->cmd_pkt->pkt_address.a_target));
6245 
6246         fpkt = cmd->cmd_fp_pkt;
6247 
6248         if (sf_core && (sf_core & SF_CORE_CMD_TIMEOUT)) {
6249                 sf_token = (int *)(uintptr_t)
6250                     fpkt->fcal_socal_request.sr_soc_hdr.\
6251                     sh_request_token;
6252                 (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6253                 sf_core = 0;
6254         }
6255 
6256         /* call the transport to abort a command */
6257         rval = soc_abort(sf->sf_sochandle, sf->sf_socp,
6258             sf->sf_sochandle->fcal_portno, fpkt, 1);
6259 
6260         switch (rval) {
6261         case FCAL_ABORTED:
6262                 SF_DEBUG(1, (sf, CE_NOTE, "Command Abort succeeded\n"));
6263                 pkt = cmd->cmd_pkt;
6264                 cmd->cmd_state = SF_STATE_IDLE;
6265                 pkt->pkt_statistics |= (STAT_TIMEOUT|STAT_ABORTED);
6266                 pkt->pkt_reason = CMD_TIMEOUT;
6267                 if (pkt->pkt_comp != NULL) {
6268                         (*pkt->pkt_comp)(pkt);
6269                 }
6270                 break;                          /* success */
6271 
6272         case FCAL_ABORT_FAILED:
6273                 SF_DEBUG(1, (sf, CE_NOTE, "Command Abort failed at target\n"));
6274                 pkt = cmd->cmd_pkt;
6275                 cmd->cmd_state = SF_STATE_IDLE;
6276                 pkt->pkt_reason = CMD_TIMEOUT;
6277                 pkt->pkt_statistics |= STAT_TIMEOUT;
6278                 tgt_id = pkt->pkt_address.a_target;
6279                 sf->sf_stats.tstats[tgt_id].abts_failures++;
6280                 if (pkt->pkt_comp != NULL) {
6281                         (*pkt->pkt_comp)(pkt);
6282                 }
6283                 break;
6284 
6285         case FCAL_BAD_ABORT:
6286                 if (sf_core && (sf_core & SF_CORE_BAD_ABORT)) {
6287                         sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6288                             sr_soc_hdr.sh_request_token;
6289                         (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6290                         sf_core = 0;
6291                 }
6292                 SF_DEBUG(1, (sf, CE_NOTE, "Command Abort bad abort\n"));
6293                 cmd->cmd_timeout = sf_watchdog_time + cmd->cmd_pkt->pkt_time
6294                     + 20;
6295                 break;
6296 
6297         case FCAL_TIMEOUT:
6298                 retval = TRUE;
6299                 break;
6300 
6301         default:
6302                 pkt = cmd->cmd_pkt;
6303                 tgt_id = pkt->pkt_address.a_target;
6304                 sf_log(sf, CE_WARN,
6305                 "Command Abort failed target 0x%x, forcing a LIP\n", tgt_id);
6306                 if (sf_core && (sf_core & SF_CORE_ABORT_TIMEOUT)) {
6307                         sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6308                             sr_soc_hdr.sh_request_token;
6309                         (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6310                         sf_core = 0;
6311                 }
6312                 sf_force_lip(sf);
6313                 retval = TRUE;
6314                 break;
6315         }
6316 
6317         return (retval);
6318 }
6319 
6320 
6321 /*
6322  * an ELS command has timed out
6323  * return ???
6324  */
6325 static struct sf_els_hdr *
6326 sf_els_timeout(struct sf *sf, struct sf_els_hdr *privp)
6327 {
6328         struct fcal_packet *fpkt;
6329         int rval, dflag, timeout = SF_ELS_TIMEOUT;
6330         uint_t lip_cnt = privp->lip_cnt;
6331         uchar_t els_code = privp->els_code;
6332         struct sf_target *target = privp->target;
6333         char what[64];
6334 
6335         fpkt = privp->fpkt;
6336         dflag = privp->delayed_retry;
6337         /* use as temporary state variable */
6338         privp->timeout = SF_INVALID_TIMEOUT;
6339         mutex_exit(&sf->sf_mutex);
6340 
6341         if (privp->fpkt->fcal_pkt_comp == sf_els_callback) {
6342                 /*
6343                  * take socal core if required. Timeouts for IB and hosts
6344                  * are not very interesting, so we take socal core only
6345                  * if the timeout is *not* for a IB or host.
6346                  */
6347                 if (sf_core && (sf_core & SF_CORE_ELS_TIMEOUT) &&
6348                     ((sf_alpa_to_switch[privp->dest_nport_id] &
6349                     0x0d) != 0x0d) && ((privp->dest_nport_id != 1) ||
6350                     (privp->dest_nport_id != 2) ||
6351                     (privp->dest_nport_id != 4) ||
6352                     (privp->dest_nport_id != 8) ||
6353                     (privp->dest_nport_id != 0xf))) {
6354                         sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6355                             sr_soc_hdr.sh_request_token;
6356                         (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6357                         sf_core = 0;
6358                 }
6359                 (void) sprintf(what, "ELS 0x%x", privp->els_code);
6360         } else if (privp->fpkt->fcal_pkt_comp == sf_reportlun_callback) {
6361                 if (sf_core && (sf_core & SF_CORE_REPORTLUN_TIMEOUT)) {
6362                         sf_token = (int *)(uintptr_t)fpkt->fcal_socal_request.\
6363                             sr_soc_hdr.sh_request_token;
6364                         (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6365                         sf_core = 0;
6366                 }
6367                 timeout = SF_FCP_TIMEOUT;
6368                 (void) sprintf(what, "REPORT_LUNS");
6369         } else if (privp->fpkt->fcal_pkt_comp == sf_inq_callback) {
6370                 if (sf_core && (sf_core & SF_CORE_INQUIRY_TIMEOUT)) {
6371                         sf_token = (int *)(uintptr_t)
6372                             fpkt->fcal_socal_request.\
6373                             sr_soc_hdr.sh_request_token;
6374                         (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6375                         sf_core = 0;
6376                 }
6377                 timeout = SF_FCP_TIMEOUT;
6378                 (void) sprintf(what, "INQUIRY to LUN 0x%lx",
6379                     (long)SCSA_LUN(target));
6380         } else {
6381                 (void) sprintf(what, "UNKNOWN OPERATION");
6382         }
6383 
6384         if (dflag) {
6385                 /* delayed retry */
6386                 SF_DEBUG(2, (sf, CE_CONT,
6387                     "!sf%d: %s to target %x delayed retry\n",
6388                     ddi_get_instance(sf->sf_dip), what,
6389                     sf_alpa_to_switch[privp->dest_nport_id]));
6390                 privp->delayed_retry = FALSE;
6391                 goto try_again;
6392         }
6393 
6394         sf_log(sf, CE_NOTE, "!%s to target 0x%x alpa 0x%x timed out\n",
6395             what, sf_alpa_to_switch[privp->dest_nport_id],
6396             privp->dest_nport_id);
6397 
6398         rval = soc_abort(sf->sf_sochandle, sf->sf_socp, sf->sf_sochandle
6399             ->fcal_portno, fpkt, 1);
6400         if (rval == FCAL_ABORTED || rval == FCAL_ABORT_FAILED) {
6401         SF_DEBUG(1, (sf, CE_NOTE, "!%s abort to al_pa %x succeeded\n",
6402             what, privp->dest_nport_id));
6403 try_again:
6404 
6405                 mutex_enter(&sf->sf_mutex);
6406                 if (privp->prev != NULL) {
6407                         privp->prev->next = privp->next;
6408                 }
6409                 if (sf->sf_els_list == privp) {
6410                         sf->sf_els_list = privp->next;
6411                 }
6412                 if (privp->next != NULL) {
6413                         privp->next->prev = privp->prev;
6414                 }
6415                 privp->prev = privp->next = NULL;
6416                 if (lip_cnt == sf->sf_lip_cnt) {
6417                         privp->timeout = sf_watchdog_time + timeout;
6418                         if ((++(privp->retries) < sf_els_retries) ||
6419                             (dflag && (privp->retries < SF_BSY_RETRIES))) {
6420                                 mutex_exit(&sf->sf_mutex);
6421                                 sf_log(sf, CE_NOTE,
6422                                     "!%s to target 0x%x retrying\n",
6423                                     what,
6424                                     sf_alpa_to_switch[privp->dest_nport_id]);
6425                                 if (sf_els_transport(sf, privp) == 1) {
6426                                         mutex_enter(&sf->sf_mutex);
6427                                         return (sf->sf_els_list); /* success */
6428                                 }
6429                                 mutex_enter(&sf->sf_mutex);
6430                                 fpkt = NULL;
6431                         }
6432                         if ((lip_cnt == sf->sf_lip_cnt) &&
6433                             (els_code != LA_ELS_LOGO)) {
6434                                 if (target != NULL) {
6435                                         sf_offline_target(sf, target);
6436                                 }
6437                                 if (sf->sf_lip_cnt == lip_cnt) {
6438                                         sf->sf_device_count--;
6439                                         ASSERT(sf->sf_device_count >= 0);
6440                                         if (sf->sf_device_count == 0) {
6441                                                 sf_finish_init(sf,
6442                                                     sf->sf_lip_cnt);
6443                                         }
6444                                 }
6445                         }
6446                         privp = sf->sf_els_list;
6447                         mutex_exit(&sf->sf_mutex);
6448                         if (fpkt != NULL) {
6449                                 sf_els_free(fpkt);
6450                         }
6451                 } else {
6452                         mutex_exit(&sf->sf_mutex);
6453                         sf_els_free(privp->fpkt);
6454                         privp = NULL;
6455                 }
6456         } else {
6457                 if (sf_core && (sf_core & SF_CORE_ELS_FAILED)) {
6458                         sf_token = (int *)(uintptr_t)
6459                             fpkt->fcal_socal_request.\
6460                             sr_soc_hdr.sh_request_token;
6461                         (void) soc_take_core(sf->sf_sochandle, sf->sf_socp);
6462                         sf_core = 0;
6463                 }
6464                 sf_log(sf, CE_NOTE, "%s abort to target 0x%x failed. "
6465                     "status=0x%x, forcing LIP\n", what,
6466                     sf_alpa_to_switch[privp->dest_nport_id], rval);
6467                 privp = NULL;
6468                 if (sf->sf_lip_cnt == lip_cnt) {
6469                         sf_force_lip(sf);
6470                 }
6471         }
6472 
6473         mutex_enter(&sf->sf_mutex);
6474         return (privp);
6475 }
6476 
6477 
6478 /*
6479  * called by timeout when a reset times out
6480  */
6481 /*ARGSUSED*/
6482 static void
6483 sf_check_reset_delay(void *arg)
6484 {
6485         struct sf *sf;
6486         struct sf_target *target;
6487         struct sf_reset_list *rp, *tp;
6488         uint_t lip_cnt, reset_timeout_flag = FALSE;
6489         clock_t lb;
6490 
6491         lb = ddi_get_lbolt();
6492 
6493         mutex_enter(&sf_global_mutex);
6494 
6495         sf_reset_timeout_id = 0;
6496 
6497         for (sf = sf_head; sf != NULL; sf = sf->sf_next) {
6498 
6499                 mutex_exit(&sf_global_mutex);
6500                 mutex_enter(&sf->sf_mutex);
6501 
6502                 /* is this type cast needed? */
6503                 tp = (struct sf_reset_list *)&sf->sf_reset_list;
6504 
6505                 rp = sf->sf_reset_list;
6506                 while (rp != NULL) {
6507                         if (((rp->timeout - lb) < 0) &&
6508                             (rp->lip_cnt == sf->sf_lip_cnt)) {
6509                                 tp->next = rp->next;
6510                                 mutex_exit(&sf->sf_mutex);
6511                                 target = rp->target;
6512                                 lip_cnt = rp->lip_cnt;
6513                                 kmem_free(rp, sizeof (struct sf_reset_list));
6514                                 /* abort all cmds for this target */
6515                                 while (target) {
6516                                         sf_abort_all(sf, target, FALSE,
6517                                             lip_cnt, TRUE);
6518                                         mutex_enter(&target->sft_mutex);
6519                                         if (lip_cnt == sf->sf_lip_cnt) {
6520                                                 target->sft_state &=
6521                                                     ~SF_TARGET_BUSY;
6522                                         }
6523                                         mutex_exit(&target->sft_mutex);
6524                                         target = target->sft_next_lun;
6525                                 }
6526                                 mutex_enter(&sf->sf_mutex);
6527                                 tp = (struct sf_reset_list *)
6528                                     &sf->sf_reset_list;
6529                                 rp = sf->sf_reset_list;
6530                                 lb = ddi_get_lbolt();
6531                         } else if (rp->lip_cnt != sf->sf_lip_cnt) {
6532                                 tp->next = rp->next;
6533                                 kmem_free(rp, sizeof (struct sf_reset_list));
6534                                 rp = tp->next;
6535                         } else {
6536                                 reset_timeout_flag = TRUE;
6537                                 tp = rp;
6538                                 rp = rp->next;
6539                         }
6540                 }
6541                 mutex_exit(&sf->sf_mutex);
6542                 mutex_enter(&sf_global_mutex);
6543         }
6544 
6545         if (reset_timeout_flag && (sf_reset_timeout_id == 0)) {
6546                 sf_reset_timeout_id = timeout(sf_check_reset_delay,
6547                     NULL, drv_usectohz(SF_TARGET_RESET_DELAY));
6548         }
6549 
6550         mutex_exit(&sf_global_mutex);
6551 }
6552 
6553 
6554 /*
6555  * called to "reset the bus", i.e. force loop initialization (and address
6556  * re-negotiation)
6557  */
6558 static void
6559 sf_force_lip(struct sf *sf)
6560 {
6561         int i;
6562         struct sf_target *target;
6563 
6564 
6565         /* disable restart of lip if we're suspended */
6566         mutex_enter(&sf->sf_mutex);
6567         if (sf->sf_state & SF_STATE_SUSPENDED) {
6568                 mutex_exit(&sf->sf_mutex);
6569                 SF_DEBUG(1, (sf, CE_CONT,
6570                     "sf_force_lip, sf%d: lip restart disabled "
6571                     "due to DDI_SUSPEND\n",
6572                     ddi_get_instance(sf->sf_dip)));
6573                 return;
6574         }
6575 
6576         sf_log(sf, CE_NOTE, "Forcing lip\n");
6577 
6578         for (i = 0; i < sf_max_targets; i++) {
6579                 target = sf->sf_targets[i];
6580                 while (target != NULL) {
6581                         mutex_enter(&target->sft_mutex);
6582                         if (!(target->sft_state & SF_TARGET_OFFLINE))
6583                                 target->sft_state |= SF_TARGET_BUSY;
6584                         mutex_exit(&target->sft_mutex);
6585                         target = target->sft_next_lun;
6586                 }
6587         }
6588 
6589         sf->sf_lip_cnt++;
6590         sf->sf_timer = sf_watchdog_time + SF_OFFLINE_TIMEOUT;
6591         sf->sf_state = SF_STATE_OFFLINE;
6592         mutex_exit(&sf->sf_mutex);
6593         sf->sf_stats.lip_count++;            /* no mutex for this? */
6594 
6595 #ifdef DEBUG
6596         /* are we allowing LIPs ?? */
6597         if (sf_lip_flag != 0) {
6598 #endif
6599                 /* call the transport to force loop initialization */
6600                 if (((i = soc_force_lip(sf->sf_sochandle, sf->sf_socp,
6601                     sf->sf_sochandle->fcal_portno, 1,
6602                     FCAL_FORCE_LIP)) != FCAL_SUCCESS) &&
6603                     (i != FCAL_TIMEOUT)) {
6604                         /* force LIP failed */
6605                         if (sf_core && (sf_core & SF_CORE_LIP_FAILED)) {
6606                                 (void) soc_take_core(sf->sf_sochandle,
6607                                     sf->sf_socp);
6608                                 sf_core = 0;
6609                         }
6610 #ifdef DEBUG
6611                         /* are we allowing reset after LIP failed ?? */
6612                         if (sf_reset_flag != 0) {
6613 #endif
6614                                 /* restart socal after resetting it */
6615                                 sf_log(sf, CE_NOTE,
6616                                     "!Force lip failed Status code 0x%x."
6617                                     " Reseting\n", i);
6618                                 /* call transport to force a reset */
6619                                 soc_force_reset(sf->sf_sochandle, sf->sf_socp,
6620                                     sf->sf_sochandle->fcal_portno, 1);
6621 #ifdef  DEBUG
6622                         }
6623 #endif
6624                 }
6625 #ifdef  DEBUG
6626         }
6627 #endif
6628 }
6629 
6630 
6631 /*
6632  * called by the transport when an unsolicited ELS is received
6633  */
6634 static void
6635 sf_unsol_els_callback(void *arg, soc_response_t *srp, caddr_t payload)
6636 {
6637         struct sf *sf = (struct sf *)arg;
6638         els_payload_t   *els = (els_payload_t *)payload;
6639         struct la_els_rjt *rsp;
6640         int     i, tgt_id;
6641         uchar_t dest_id;
6642         struct fcal_packet *fpkt;
6643         fc_frame_header_t *hp;
6644         struct sf_els_hdr *privp;
6645 
6646 
6647         if ((els == NULL) || ((i = srp->sr_soc_hdr.sh_byte_cnt) == 0)) {
6648                 return;
6649         }
6650 
6651         if (i > SOC_CQE_PAYLOAD) {
6652                 i = SOC_CQE_PAYLOAD;
6653         }
6654 
6655         dest_id = (uchar_t)srp->sr_fc_frame_hdr.s_id;
6656         tgt_id = sf_alpa_to_switch[dest_id];
6657 
6658         switch (els->els_cmd.c.ls_command) {
6659 
6660         case LA_ELS_LOGO:
6661                 /*
6662                  * logout received -- log the fact
6663                  */
6664                 sf->sf_stats.tstats[tgt_id].logouts_recvd++;
6665                 sf_log(sf, CE_NOTE, "!LOGO recvd from target %x, %s\n",
6666                     tgt_id,
6667                     sf_lip_on_plogo ? "Forcing LIP...." : "");
6668                 if (sf_lip_on_plogo) {
6669                         sf_force_lip(sf);
6670                 }
6671                 break;
6672 
6673         default:  /* includes LA_ELS_PLOGI */
6674                 /*
6675                  * something besides a logout received -- we don't handle
6676                  * this so send back a reject saying its unsupported
6677                  */
6678 
6679                 sf_log(sf, CE_NOTE, "!ELS 0x%x recvd from target 0x%x\n",
6680                     els->els_cmd.c.ls_command, tgt_id);
6681 
6682 
6683                 /* allocate room for a response */
6684                 if (sf_els_alloc(sf, dest_id, sizeof (struct sf_els_hdr),
6685                     sizeof (struct la_els_rjt), sizeof (union sf_els_rsp),
6686                     (caddr_t *)&privp, (caddr_t *)&rsp) == NULL) {
6687                         break;
6688                 }
6689 
6690                 fpkt = privp->fpkt;
6691 
6692                 /* fill in pkt header */
6693                 hp = &fpkt->fcal_socal_request.sr_fc_frame_hdr;
6694                 hp->r_ctl = R_CTL_ELS_RSP;
6695                 hp->f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
6696                 hp->ox_id = srp->sr_fc_frame_hdr.ox_id;
6697                 hp->rx_id = srp->sr_fc_frame_hdr.rx_id;
6698                 fpkt->fcal_socal_request.sr_cqhdr.cq_hdr_type =
6699                     CQ_TYPE_OUTBOUND;
6700 
6701                 fpkt->fcal_socal_request.sr_soc_hdr.sh_seg_cnt = 1;
6702 
6703                 /* fill in response */
6704                 rsp->ls_code = LA_ELS_RJT;   /* reject this ELS */
6705                 rsp->mbz[0] = 0;
6706                 rsp->mbz[1] = 0;
6707                 rsp->mbz[2] = 0;
6708                 ((struct la_els_logi *)privp->rsp)->ls_code = LA_ELS_ACC;
6709                 *((int *)&rsp->reserved) = 0;
6710                 rsp->reason_code = RJT_UNSUPPORTED;
6711                 privp->retries = sf_els_retries;
6712                 privp->els_code = LA_ELS_RJT;
6713                 privp->timeout = (unsigned)0xffffffff;
6714                 (void) sf_els_transport(sf, privp);
6715                 break;
6716         }
6717 }
6718 
6719 
6720 /*
6721  * Error logging, printing, and debug print routines
6722  */
6723 
6724 /*PRINTFLIKE3*/
6725 static void
6726 sf_log(struct sf *sf, int level, const char *fmt, ...)
6727 {
6728         char buf[256];
6729         dev_info_t *dip;
6730         va_list ap;
6731 
6732         if (sf != NULL) {
6733                 dip = sf->sf_dip;
6734         } else {
6735                 dip = NULL;
6736         }
6737 
6738         va_start(ap, fmt);
6739         (void) vsprintf(buf, fmt, ap);
6740         va_end(ap);
6741         scsi_log(dip, "sf", level, buf);
6742 }
6743 
6744 
6745 /*
6746  * called to get some sf kstats -- return 0 on success else return errno
6747  */
6748 static int
6749 sf_kstat_update(kstat_t *ksp, int rw)
6750 {
6751         struct sf *sf;
6752 
6753         if (rw == KSTAT_WRITE) {
6754                 /* can't write */
6755                 return (EACCES);
6756         }
6757 
6758         sf = ksp->ks_private;
6759         sf->sf_stats.ncmds = sf->sf_ncmds;
6760         sf->sf_stats.throttle_limit = sf->sf_throttle;
6761         sf->sf_stats.cr_pool_size = sf->sf_cr_pool_cnt;
6762 
6763         return (0);                             /* success */
6764 }
6765 
6766 
6767 /*
6768  * Unix Entry Points
6769  */
6770 
6771 /*
6772  * driver entry point for opens on control device
6773  */
6774 /* ARGSUSED */
6775 static int
6776 sf_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
6777 {
6778         dev_t dev = *dev_p;
6779         struct sf *sf;
6780 
6781 
6782         /* just ensure soft state exists for this device */
6783         sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
6784         if (sf == NULL) {
6785                 return (ENXIO);
6786         }
6787 
6788         ++(sf->sf_check_n_close);
6789 
6790         return (0);
6791 }
6792 
6793 
6794 /*
6795  * driver entry point for last close on control device
6796  */
6797 /* ARGSUSED */
6798 static int
6799 sf_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
6800 {
6801         struct sf *sf;
6802 
6803         sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
6804         if (sf == NULL) {
6805                 return (ENXIO);
6806         }
6807 
6808         if (!sf->sf_check_n_close) { /* if this flag is zero */
6809                 cmn_err(CE_WARN, "sf%d: trying to close unopened instance",
6810                     SF_MINOR2INST(getminor(dev)));
6811                 return (ENODEV);
6812         } else {
6813                 --(sf->sf_check_n_close);
6814         }
6815         return (0);
6816 }
6817 
6818 
6819 /*
6820  * driver entry point for sf ioctl commands
6821  */
6822 /* ARGSUSED */
6823 static int
6824 sf_ioctl(dev_t dev,
6825     int cmd, intptr_t arg, int mode, cred_t *cred_p, int *rval_p)
6826 {
6827         struct sf *sf;
6828         struct sf_target *target;
6829         uchar_t al_pa;
6830         struct sf_al_map map;
6831         int cnt, i;
6832         int     retval;                         /* return value */
6833         struct devctl_iocdata *dcp;
6834         dev_info_t *cdip;
6835         struct scsi_address ap;
6836         scsi_hba_tran_t *tran;
6837 
6838 
6839         sf = ddi_get_soft_state(sf_state, SF_MINOR2INST(getminor(dev)));
6840         if (sf == NULL) {
6841                 return (ENXIO);
6842         }
6843 
6844         /* handle all ioctls */
6845         switch (cmd) {
6846 
6847         /*
6848          * We can use the generic implementation for these ioctls
6849          */
6850         case DEVCTL_DEVICE_GETSTATE:
6851         case DEVCTL_DEVICE_ONLINE:
6852         case DEVCTL_DEVICE_OFFLINE:
6853         case DEVCTL_BUS_GETSTATE:
6854                 return (ndi_devctl_ioctl(sf->sf_dip, cmd, arg, mode, 0));
6855 
6856         /*
6857          * return FC map
6858          */
6859         case SFIOCGMAP:
6860                 if ((sf->sf_lilp_map->lilp_magic != FCAL_LILP_MAGIC &&
6861                     sf->sf_lilp_map->lilp_magic != FCAL_BADLILP_MAGIC) ||
6862                     sf->sf_state != SF_STATE_ONLINE) {
6863                         retval = ENOENT;
6864                         goto dun;
6865                 }
6866                 mutex_enter(&sf->sf_mutex);
6867                 if (sf->sf_lilp_map->lilp_magic == FCAL_BADLILP_MAGIC) {
6868                         int i, j = 0;
6869 
6870                         /* Need to generate a fake lilp map */
6871                         for (i = 0; i < sf_max_targets; i++) {
6872                                 if (sf->sf_targets[i])
6873                                         sf->sf_lilp_map->lilp_alpalist[j++] =
6874                                             sf->sf_targets[i]->
6875                                             sft_hard_address;
6876                         }
6877                         sf->sf_lilp_map->lilp_length = (uchar_t)j;
6878                 }
6879                 cnt = sf->sf_lilp_map->lilp_length;
6880                 map.sf_count = (short)cnt;
6881                 bcopy((caddr_t)&sf->sf_sochandle->fcal_n_wwn,
6882                     (caddr_t)&map.sf_hba_addr.sf_node_wwn,
6883                     sizeof (la_wwn_t));
6884                 bcopy((caddr_t)&sf->sf_sochandle->fcal_p_wwn,
6885                     (caddr_t)&map.sf_hba_addr.sf_port_wwn,
6886                     sizeof (la_wwn_t));
6887                 map.sf_hba_addr.sf_al_pa = sf->sf_al_pa;
6888                 map.sf_hba_addr.sf_hard_address = 0;
6889                 map.sf_hba_addr.sf_inq_dtype = DTYPE_UNKNOWN;
6890                 for (i = 0; i < cnt; i++) {
6891                         al_pa = sf->sf_lilp_map->lilp_alpalist[i];
6892                         map.sf_addr_pair[i].sf_al_pa = al_pa;
6893                         if (al_pa == sf->sf_al_pa) {
6894                                 (void) bcopy((caddr_t)&sf->sf_sochandle
6895                                     ->fcal_n_wwn, (caddr_t)&map.
6896                                     sf_addr_pair[i].sf_node_wwn,
6897                                     sizeof (la_wwn_t));
6898                                 (void) bcopy((caddr_t)&sf->sf_sochandle
6899                                     ->fcal_p_wwn, (caddr_t)&map.
6900                                     sf_addr_pair[i].sf_port_wwn,
6901                                     sizeof (la_wwn_t));
6902                                 map.sf_addr_pair[i].sf_hard_address =
6903                                     al_pa;
6904                                 map.sf_addr_pair[i].sf_inq_dtype =
6905                                     DTYPE_PROCESSOR;
6906                                 continue;
6907                         }
6908                         target = sf->sf_targets[sf_alpa_to_switch[
6909                             al_pa]];
6910                         if (target != NULL) {
6911                                 mutex_enter(&target->sft_mutex);
6912                                 if (!(target->sft_state &
6913                                     (SF_TARGET_OFFLINE |
6914                                     SF_TARGET_BUSY))) {
6915                                         bcopy((caddr_t)&target->
6916                                             sft_node_wwn,
6917                                             (caddr_t)&map.sf_addr_pair
6918                                             [i].sf_node_wwn,
6919                                             sizeof (la_wwn_t));
6920                                         bcopy((caddr_t)&target->
6921                                             sft_port_wwn,
6922                                             (caddr_t)&map.sf_addr_pair
6923                                             [i].sf_port_wwn,
6924                                             sizeof (la_wwn_t));
6925                                         map.sf_addr_pair[i].
6926                                             sf_hard_address
6927                                             = target->sft_hard_address;
6928                                         map.sf_addr_pair[i].
6929                                             sf_inq_dtype
6930                                             = target->sft_device_type;
6931                                         mutex_exit(&target->sft_mutex);
6932                                         continue;
6933                                 }
6934                                 mutex_exit(&target->sft_mutex);
6935                         }
6936                         bzero((caddr_t)&map.sf_addr_pair[i].
6937                             sf_node_wwn, sizeof (la_wwn_t));
6938                         bzero((caddr_t)&map.sf_addr_pair[i].
6939                             sf_port_wwn, sizeof (la_wwn_t));
6940                         map.sf_addr_pair[i].sf_inq_dtype =
6941                             DTYPE_UNKNOWN;
6942                 }
6943                 mutex_exit(&sf->sf_mutex);
6944                 if (ddi_copyout((caddr_t)&map, (caddr_t)arg,
6945                     sizeof (struct sf_al_map), mode) != 0) {
6946                         retval = EFAULT;
6947                         goto dun;
6948                 }
6949                 break;
6950 
6951         /*
6952          * handle device control ioctls
6953          */
6954         case DEVCTL_DEVICE_RESET:
6955                 if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) {
6956                         retval = EFAULT;
6957                         goto dun;
6958                 }
6959                 if ((ndi_dc_getname(dcp) == NULL) ||
6960                     (ndi_dc_getaddr(dcp) == NULL)) {
6961                         ndi_dc_freehdl(dcp);
6962                         retval = EINVAL;
6963                         goto dun;
6964                 }
6965                 cdip = ndi_devi_find(sf->sf_dip,
6966                     ndi_dc_getname(dcp), ndi_dc_getaddr(dcp));
6967                 ndi_dc_freehdl(dcp);
6968 
6969                 if (cdip == NULL) {
6970                         retval = ENXIO;
6971                         goto dun;
6972                 }
6973 
6974                 if ((target = sf_get_target_from_dip(sf, cdip)) == NULL) {
6975                         retval = ENXIO;
6976                         goto dun;
6977                 }
6978                 mutex_enter(&target->sft_mutex);
6979                 if (!(target->sft_state & SF_TARGET_INIT_DONE)) {
6980                         mutex_exit(&target->sft_mutex);
6981                         retval = ENXIO;
6982                         goto dun;
6983                 }
6984 
6985                 /* This is ugly */
6986                 tran = kmem_zalloc(scsi_hba_tran_size(), KM_SLEEP);
6987                 bcopy(target->sft_tran, tran, scsi_hba_tran_size());
6988                 mutex_exit(&target->sft_mutex);
6989                 ap.a_hba_tran = tran;
6990                 ap.a_target = sf_alpa_to_switch[target->sft_al_pa];
6991                 if (sf_reset(&ap, RESET_TARGET) == FALSE) {
6992                         retval = EIO;
6993                 } else {
6994                         retval = 0;
6995                 }
6996                 kmem_free(tran, scsi_hba_tran_size());
6997                 goto dun;
6998 
6999         case DEVCTL_BUS_QUIESCE:
7000         case DEVCTL_BUS_UNQUIESCE:
7001                 retval = ENOTSUP;
7002                 goto dun;
7003 
7004         case DEVCTL_BUS_RESET:
7005         case DEVCTL_BUS_RESETALL:
7006                 sf_force_lip(sf);
7007                 break;
7008 
7009         default:
7010                 retval = ENOTTY;
7011                 goto dun;
7012         }
7013 
7014         retval = 0;                             /* success */
7015 
7016 dun:
7017         return (retval);
7018 }
7019 
7020 
7021 /*
7022  * get the target given a DIP
7023  */
7024 static struct sf_target *
7025 sf_get_target_from_dip(struct sf *sf, dev_info_t *dip)
7026 {
7027         int i;
7028         struct sf_target *target;
7029 
7030 
7031         /* scan each hash queue for the DIP in question */
7032         for (i = 0; i < SF_NUM_HASH_QUEUES; i++) {
7033                 target = sf->sf_wwn_lists[i];
7034                 while (target != NULL) {
7035                         if (target->sft_dip == dip) {
7036                                 return (target); /* success: target found */
7037                         }
7038                         target = target->sft_next;
7039                 }
7040         }
7041         return (NULL);                          /* failure: target not found */
7042 }
7043 
7044 
7045 /*
7046  * called by the transport to get an event cookie
7047  */
7048 static int
7049 sf_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
7050     ddi_eventcookie_t *event_cookiep)
7051 {
7052         struct sf *sf;
7053 
7054         sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
7055         if (sf == NULL) {
7056                 /* can't find instance for this device */
7057                 return (DDI_FAILURE);
7058         }
7059 
7060         return (ndi_event_retrieve_cookie(sf->sf_event_hdl, rdip, name,
7061             event_cookiep, NDI_EVENT_NOPASS));
7062 
7063 }
7064 
7065 
7066 /*
7067  * called by the transport to add an event callback
7068  */
7069 static int
7070 sf_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
7071     ddi_eventcookie_t eventid, void (*callback)(dev_info_t *dip,
7072     ddi_eventcookie_t event, void *arg, void *impl_data), void *arg,
7073     ddi_callback_id_t *cb_id)
7074 {
7075         struct sf *sf;
7076 
7077         sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
7078         if (sf == NULL) {
7079                 /* can't find instance for this device */
7080                 return (DDI_FAILURE);
7081         }
7082 
7083         return (ndi_event_add_callback(sf->sf_event_hdl, rdip,
7084             eventid, callback, arg, NDI_SLEEP, cb_id));
7085 
7086 }
7087 
7088 
7089 /*
7090  * called by the transport to remove an event callback
7091  */
7092 static int
7093 sf_bus_remove_eventcall(dev_info_t *devi, ddi_callback_id_t cb_id)
7094 {
7095         struct sf *sf;
7096 
7097         sf = ddi_get_soft_state(sf_state, ddi_get_instance(devi));
7098         if (sf == NULL) {
7099                 /* can't find instance for this device */
7100                 return (DDI_FAILURE);
7101         }
7102 
7103         return (ndi_event_remove_callback(sf->sf_event_hdl, cb_id));
7104 }
7105 
7106 
7107 /*
7108  * called by the transport to post an event
7109  */
7110 static int
7111 sf_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
7112     ddi_eventcookie_t eventid, void *impldata)
7113 {
7114         ddi_eventcookie_t remove_cookie, cookie;
7115 
7116         /* is this a remove event ?? */
7117         struct sf *sf = ddi_get_soft_state(sf_state, ddi_get_instance(dip));
7118         remove_cookie = ndi_event_tag_to_cookie(sf->sf_event_hdl,
7119             SF_EVENT_TAG_REMOVE);
7120 
7121         if (remove_cookie == eventid) {
7122                 struct sf_target *target;
7123 
7124                 /* handle remove event */
7125 
7126                 if (sf == NULL) {
7127                         /* no sf instance for this device */
7128                         return (NDI_FAILURE);
7129                 }
7130 
7131                 /* get the target for this event */
7132                 if ((target = sf_get_target_from_dip(sf, rdip)) != NULL) {
7133                         /*
7134                          * clear device info for this target and mark as
7135                          * not done
7136                          */
7137                         mutex_enter(&target->sft_mutex);
7138                         target->sft_dip = NULL;
7139                         target->sft_state &= ~SF_TARGET_INIT_DONE;
7140                         mutex_exit(&target->sft_mutex);
7141                         return (NDI_SUCCESS); /* event handled */
7142                 }
7143 
7144                 /* no target for this event */
7145                 return (NDI_FAILURE);
7146         }
7147 
7148         /* an insertion event */
7149         if (ndi_busop_get_eventcookie(dip, rdip, FCAL_INSERT_EVENT, &cookie)
7150             != NDI_SUCCESS) {
7151                 return (NDI_FAILURE);
7152         }
7153 
7154         return (ndi_post_event(dip, rdip, cookie, impldata));
7155 }
7156 
7157 
7158 /*
7159  * the sf hotplug daemon, one thread per sf instance
7160  */
7161 static void
7162 sf_hp_daemon(void *arg)
7163 {
7164         struct sf *sf = (struct sf *)arg;
7165         struct sf_hp_elem *elem;
7166         struct sf_target *target;
7167         int tgt_id;
7168         callb_cpr_t cprinfo;
7169 
7170         CALLB_CPR_INIT(&cprinfo, &sf->sf_hp_daemon_mutex,
7171             callb_generic_cpr, "sf_hp_daemon");
7172 
7173         mutex_enter(&sf->sf_hp_daemon_mutex);
7174 
7175         do {
7176                 while (sf->sf_hp_elem_head != NULL) {
7177 
7178                         /* save ptr to head of list */
7179                         elem = sf->sf_hp_elem_head;
7180 
7181                         /* take element off of list */
7182                         if (sf->sf_hp_elem_head == sf->sf_hp_elem_tail) {
7183                                 /* element only one in list -- list now empty */
7184                                 sf->sf_hp_elem_head = NULL;
7185                                 sf->sf_hp_elem_tail = NULL;
7186                         } else {
7187                                 /* remove element from head of list */
7188                                 sf->sf_hp_elem_head = sf->sf_hp_elem_head->next;
7189                         }
7190 
7191                         mutex_exit(&sf->sf_hp_daemon_mutex);
7192 
7193                         switch (elem->what) {
7194                         case SF_ONLINE:
7195                                 /* online this target */
7196                                 target = elem->target;
7197                                 (void) ndi_devi_online(elem->dip, 0);
7198                                 (void) ndi_event_retrieve_cookie(
7199                                     sf->sf_event_hdl,
7200                                     target->sft_dip, FCAL_INSERT_EVENT,
7201                                     &sf_insert_eid, NDI_EVENT_NOPASS);
7202                                 (void) ndi_event_run_callbacks(sf->sf_event_hdl,
7203                                     target->sft_dip, sf_insert_eid, NULL);
7204                                 break;
7205                         case SF_OFFLINE:
7206                                 /* offline this target */
7207                                 target = elem->target;
7208                                 tgt_id = sf_alpa_to_switch[target->sft_al_pa];
7209                                 /* don't do NDI_DEVI_REMOVE for now */
7210                                 if (ndi_devi_offline(elem->dip, 0) !=
7211                                     NDI_SUCCESS) {
7212                                         SF_DEBUG(1, (sf, CE_WARN, "target %x, "
7213                                             "device offline failed", tgt_id));
7214                                 } else {
7215                                         SF_DEBUG(1, (sf, CE_NOTE, "target %x, "
7216                                             "device offline succeeded\n",
7217                                             tgt_id));
7218                                 }
7219                                 break;
7220                         }
7221                         kmem_free(elem, sizeof (struct sf_hp_elem));
7222                         mutex_enter(&sf->sf_hp_daemon_mutex);
7223                 }
7224 
7225                 /* if exit is not already signaled */
7226                 if (sf->sf_hp_exit == 0) {
7227                         /* wait to be signaled by work or exit */
7228                         CALLB_CPR_SAFE_BEGIN(&cprinfo);
7229                         cv_wait(&sf->sf_hp_daemon_cv, &sf->sf_hp_daemon_mutex);
7230                         CALLB_CPR_SAFE_END(&cprinfo, &sf->sf_hp_daemon_mutex);
7231                 }
7232         } while (sf->sf_hp_exit == 0);
7233 
7234         /* sf_hp_daemon_mutex is dropped by CALLB_CPR_EXIT */
7235         CALLB_CPR_EXIT(&cprinfo);
7236         thread_exit();                  /* no more hotplug thread */
7237         /* NOTREACHED */
7238 }