xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c (revision a25672a1f5bcd6aa4bbce28adab51d84ae202323)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 #include <sys/scsi/adapters/pmcs/pmcs.h>
26 
27 #define	PMCS_DRIVER_VERSION	"pmcs HBA device driver"
28 
29 static	char	*pmcs_driver_rev = PMCS_DRIVER_VERSION;
30 
31 /*
32  * Non-DDI Compliant stuff
33  */
34 extern char hw_serial[];
35 
36 /*
37  * Global driver data
38  */
39 void *pmcs_softc_state = NULL;
40 void *pmcs_iport_softstate = NULL;
41 
42 /*
43  * Tracing and Logging info
44  */
45 pmcs_tbuf_t *pmcs_tbuf = NULL;
46 uint32_t pmcs_tbuf_num_elems = 0;
47 pmcs_tbuf_t *pmcs_tbuf_ptr;
48 uint32_t pmcs_tbuf_idx = 0;
49 boolean_t pmcs_tbuf_wrap = B_FALSE;
50 static kmutex_t pmcs_trace_lock;
51 
52 /*
53  * If pmcs_force_syslog value is non-zero, all messages put in the trace log
54  * will also be sent to system log.
55  */
56 int pmcs_force_syslog = 0;
57 int pmcs_console = 0;
58 
59 /*
60  * External References
61  */
62 extern int ncpus_online;
63 
64 /*
65  * Local static data
66  */
67 static int fwlog_level = 3;
68 static int physpeed = PHY_LINK_ALL;
69 static int phymode = PHY_LM_AUTO;
70 static int block_mask = 0;
71 static int phymap_usec = 3 * MICROSEC;
72 static int iportmap_usec = 2 * MICROSEC;
73 
74 #ifdef DEBUG
75 static int debug_mask = 1;
76 #else
77 static int debug_mask = 0;
78 #endif
79 
80 #ifdef DISABLE_MSIX
81 static int disable_msix = 1;
82 #else
83 static int disable_msix = 0;
84 #endif
85 
86 #ifdef DISABLE_MSI
87 static int disable_msi = 1;
88 #else
89 static int disable_msi = 0;
90 #endif
91 
92 static uint16_t maxqdepth = 0xfffe;
93 
94 /*
95  * Local prototypes
96  */
97 static int pmcs_attach(dev_info_t *, ddi_attach_cmd_t);
98 static int pmcs_detach(dev_info_t *, ddi_detach_cmd_t);
99 static int pmcs_unattach(pmcs_hw_t *);
100 static int pmcs_iport_unattach(pmcs_iport_t *);
101 static int pmcs_add_more_chunks(pmcs_hw_t *, unsigned long);
102 static void pmcs_watchdog(void *);
103 static int pmcs_setup_intr(pmcs_hw_t *);
104 static int pmcs_teardown_intr(pmcs_hw_t *);
105 
106 static uint_t pmcs_nonio_ix(caddr_t, caddr_t);
107 static uint_t pmcs_general_ix(caddr_t, caddr_t);
108 static uint_t pmcs_event_ix(caddr_t, caddr_t);
109 static uint_t pmcs_iodone_ix(caddr_t, caddr_t);
110 static uint_t pmcs_fatal_ix(caddr_t, caddr_t);
111 static uint_t pmcs_all_intr(caddr_t, caddr_t);
112 static int pmcs_quiesce(dev_info_t *dip);
113 static boolean_t pmcs_fabricate_wwid(pmcs_hw_t *);
114 
115 static void pmcs_create_phy_stats(pmcs_iport_t *);
116 int pmcs_update_phy_stats(kstat_t *, int);
117 static void pmcs_destroy_phy_stats(pmcs_iport_t *);
118 
119 static void pmcs_fm_fini(pmcs_hw_t *pwp);
120 static void pmcs_fm_init(pmcs_hw_t *pwp);
121 static int pmcs_fm_error_cb(dev_info_t *dip,
122     ddi_fm_error_t *err, const void *impl_data);
123 
124 /*
125  * Local configuration data
126  */
127 static struct dev_ops pmcs_ops = {
128 	DEVO_REV,		/* devo_rev, */
129 	0,			/* refcnt */
130 	ddi_no_info,		/* info */
131 	nulldev,		/* identify */
132 	nulldev,		/* probe */
133 	pmcs_attach,		/* attach */
134 	pmcs_detach,		/* detach */
135 	nodev,			/* reset */
136 	NULL,			/* driver operations */
137 	NULL,			/* bus operations */
138 	ddi_power,		/* power management */
139 	pmcs_quiesce		/* quiesce */
140 };
141 
142 static struct modldrv modldrv = {
143 	&mod_driverops,
144 	PMCS_DRIVER_VERSION,
145 	&pmcs_ops,	/* driver ops */
146 };
147 static struct modlinkage modlinkage = {
148 	MODREV_1, &modldrv, NULL
149 };
150 
151 const ddi_dma_attr_t pmcs_dattr = {
152 	DMA_ATTR_V0,			/* dma_attr version	*/
153 	0x0000000000000000ull,		/* dma_attr_addr_lo	*/
154 	0xFFFFFFFFFFFFFFFFull,		/* dma_attr_addr_hi	*/
155 	0x00000000FFFFFFFFull,		/* dma_attr_count_max	*/
156 	0x0000000000000001ull,		/* dma_attr_align	*/
157 	0x00000078,			/* dma_attr_burstsizes	*/
158 	0x00000001,			/* dma_attr_minxfer	*/
159 	0x00000000FFFFFFFFull,		/* dma_attr_maxxfer	*/
160 	0x00000000FFFFFFFFull,		/* dma_attr_seg		*/
161 	1,				/* dma_attr_sgllen 	*/
162 	512,				/* dma_attr_granular 	*/
163 	0				/* dma_attr_flags 	*/
164 };
165 
166 static ddi_device_acc_attr_t rattr = {
167 	DDI_DEVICE_ATTR_V1,
168 	DDI_STRUCTURE_LE_ACC,
169 	DDI_STRICTORDER_ACC,
170 	DDI_DEFAULT_ACC
171 };
172 
173 
174 /*
175  * Attach/Detach functions
176  */
177 
178 int
179 _init(void)
180 {
181 	int ret;
182 
183 	ret = ddi_soft_state_init(&pmcs_softc_state, sizeof (pmcs_hw_t), 1);
184 	if (ret != 0) {
185 		cmn_err(CE_WARN, "?soft state init failed for pmcs");
186 		return (ret);
187 	}
188 
189 	if ((ret = scsi_hba_init(&modlinkage)) != 0) {
190 		cmn_err(CE_WARN, "?scsi_hba_init failed for pmcs");
191 		ddi_soft_state_fini(&pmcs_softc_state);
192 		return (ret);
193 	}
194 
195 	/*
196 	 * Allocate soft state for iports
197 	 */
198 	ret = ddi_soft_state_init(&pmcs_iport_softstate,
199 	    sizeof (pmcs_iport_t), 2);
200 	if (ret != 0) {
201 		cmn_err(CE_WARN, "?iport soft state init failed for pmcs");
202 		ddi_soft_state_fini(&pmcs_softc_state);
203 		return (ret);
204 	}
205 
206 	ret = mod_install(&modlinkage);
207 	if (ret != 0) {
208 		cmn_err(CE_WARN, "?mod_install failed for pmcs (%d)", ret);
209 		scsi_hba_fini(&modlinkage);
210 		ddi_soft_state_fini(&pmcs_iport_softstate);
211 		ddi_soft_state_fini(&pmcs_softc_state);
212 		return (ret);
213 	}
214 
215 	/* Initialize the global trace lock */
216 	mutex_init(&pmcs_trace_lock, NULL, MUTEX_DRIVER, NULL);
217 
218 	return (0);
219 }
220 
221 int
222 _fini(void)
223 {
224 	int ret;
225 	if ((ret = mod_remove(&modlinkage)) != 0) {
226 		return (ret);
227 	}
228 	scsi_hba_fini(&modlinkage);
229 
230 	/* Free pmcs log buffer and destroy the global lock */
231 	if (pmcs_tbuf) {
232 		kmem_free(pmcs_tbuf,
233 		    pmcs_tbuf_num_elems * sizeof (pmcs_tbuf_t));
234 		pmcs_tbuf = NULL;
235 	}
236 	mutex_destroy(&pmcs_trace_lock);
237 
238 	ddi_soft_state_fini(&pmcs_iport_softstate);
239 	ddi_soft_state_fini(&pmcs_softc_state);
240 	return (0);
241 }
242 
243 int
244 _info(struct modinfo *modinfop)
245 {
246 	return (mod_info(&modlinkage, modinfop));
247 }
248 
249 static int
250 pmcs_iport_attach(dev_info_t *dip)
251 {
252 	pmcs_iport_t		*iport;
253 	pmcs_hw_t		*pwp;
254 	scsi_hba_tran_t		*tran;
255 	void			*ua_priv = NULL;
256 	char			*iport_ua;
257 	char			*init_port;
258 	int			hba_inst;
259 	int			inst;
260 
261 	hba_inst = ddi_get_instance(ddi_get_parent(dip));
262 	inst = ddi_get_instance(dip);
263 
264 	pwp = ddi_get_soft_state(pmcs_softc_state, hba_inst);
265 	if (pwp == NULL) {
266 		cmn_err(CE_WARN, "%s: No HBA softstate for instance %d",
267 		    __func__, inst);
268 		return (DDI_FAILURE);
269 	}
270 
271 	if ((pwp->state == STATE_UNPROBING) || (pwp->state == STATE_DEAD)) {
272 		return (DDI_FAILURE);
273 	}
274 
275 	if ((iport_ua = scsi_hba_iport_unit_address(dip)) == NULL) {
276 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
277 		    "%s: invoked with NULL unit address, inst (%d)",
278 		    __func__, inst);
279 		return (DDI_FAILURE);
280 	}
281 
282 	if (ddi_soft_state_zalloc(pmcs_iport_softstate, inst) != DDI_SUCCESS) {
283 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
284 		    "Failed to alloc soft state for iport %d", inst);
285 		return (DDI_FAILURE);
286 	}
287 
288 	iport = ddi_get_soft_state(pmcs_iport_softstate, inst);
289 	if (iport == NULL) {
290 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
291 		    "cannot get iport soft state");
292 		goto iport_attach_fail1;
293 	}
294 
295 	mutex_init(&iport->lock, NULL, MUTEX_DRIVER,
296 	    DDI_INTR_PRI(pwp->intr_pri));
297 	cv_init(&iport->refcnt_cv, NULL, CV_DEFAULT, NULL);
298 	cv_init(&iport->smp_cv, NULL, CV_DEFAULT, NULL);
299 	mutex_init(&iport->refcnt_lock, NULL, MUTEX_DRIVER,
300 	    DDI_INTR_PRI(pwp->intr_pri));
301 	mutex_init(&iport->smp_lock, NULL, MUTEX_DRIVER,
302 	    DDI_INTR_PRI(pwp->intr_pri));
303 
304 	/* Set some data on the iport handle */
305 	iport->dip = dip;
306 	iport->pwp = pwp;
307 
308 	/* Dup the UA into the iport handle */
309 	iport->ua = strdup(iport_ua);
310 
311 	tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
312 	tran->tran_hba_private = iport;
313 
314 	list_create(&iport->phys, sizeof (pmcs_phy_t),
315 	    offsetof(pmcs_phy_t, list_node));
316 
317 	/*
318 	 * If our unit address is active in the phymap, configure our
319 	 * iport's phylist.
320 	 */
321 	mutex_enter(&iport->lock);
322 	ua_priv = sas_phymap_lookup_uapriv(pwp->hss_phymap, iport->ua);
323 	if (ua_priv) {
324 		/* Non-NULL private data indicates the unit address is active */
325 		iport->ua_state = UA_ACTIVE;
326 		if (pmcs_iport_configure_phys(iport) != DDI_SUCCESS) {
327 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
328 			    "%s: failed to "
329 			    "configure phys on iport handle (0x%p), "
330 			    " unit address [%s]", __func__,
331 			    (void *)iport, iport_ua);
332 			mutex_exit(&iport->lock);
333 			goto iport_attach_fail2;
334 		}
335 	} else {
336 		iport->ua_state = UA_INACTIVE;
337 	}
338 	mutex_exit(&iport->lock);
339 
340 	/* Allocate string-based soft state pool for targets */
341 	iport->tgt_sstate = NULL;
342 	if (ddi_soft_state_bystr_init(&iport->tgt_sstate,
343 	    sizeof (pmcs_xscsi_t), PMCS_TGT_SSTATE_SZ) != 0) {
344 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
345 		    "cannot get iport tgt soft state");
346 		goto iport_attach_fail2;
347 	}
348 
349 	/* Create this iport's target map */
350 	if (pmcs_iport_tgtmap_create(iport) == B_FALSE) {
351 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
352 		    "Failed to create tgtmap on iport %d", inst);
353 		goto iport_attach_fail3;
354 	}
355 
356 	/* Set up the 'initiator-port' DDI property on this iport */
357 	init_port = kmem_zalloc(PMCS_MAX_UA_SIZE, KM_SLEEP);
358 	if (pwp->separate_ports) {
359 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
360 		    "%s: separate ports not supported", __func__);
361 	} else {
362 		/* Set initiator-port value to the HBA's base WWN */
363 		(void) scsi_wwn_to_wwnstr(pwp->sas_wwns[0], 1,
364 		    init_port);
365 	}
366 
367 	mutex_enter(&iport->lock);
368 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_STRING,
369 	    SCSI_ADDR_PROP_INITIATOR_PORT, init_port);
370 	kmem_free(init_port, PMCS_MAX_UA_SIZE);
371 
372 	/* Set up a 'num-phys' DDI property for the iport node */
373 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
374 	    &iport->nphy);
375 	mutex_exit(&iport->lock);
376 
377 	/* Create kstats for each of the phys in this port */
378 	pmcs_create_phy_stats(iport);
379 
380 	/*
381 	 * Insert this iport handle into our list and set
382 	 * iports_attached on the HBA node.
383 	 */
384 	rw_enter(&pwp->iports_lock, RW_WRITER);
385 	ASSERT(!list_link_active(&iport->list_node));
386 	list_insert_tail(&pwp->iports, iport);
387 	pwp->iports_attached = 1;
388 	pwp->num_iports++;
389 	rw_exit(&pwp->iports_lock);
390 
391 	pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
392 	    "iport%d attached", inst);
393 	ddi_report_dev(dip);
394 	return (DDI_SUCCESS);
395 
396 	/* teardown and fail */
397 iport_attach_fail3:
398 	ddi_soft_state_bystr_fini(&iport->tgt_sstate);
399 iport_attach_fail2:
400 	list_destroy(&iport->phys);
401 	strfree(iport->ua);
402 	mutex_destroy(&iport->refcnt_lock);
403 	mutex_destroy(&iport->smp_lock);
404 	cv_destroy(&iport->refcnt_cv);
405 	cv_destroy(&iport->smp_cv);
406 	mutex_destroy(&iport->lock);
407 iport_attach_fail1:
408 	ddi_soft_state_free(pmcs_iport_softstate, inst);
409 	return (DDI_FAILURE);
410 }
411 
412 static int
413 pmcs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
414 {
415 	scsi_hba_tran_t *tran;
416 	char chiprev, *fwsupport, hw_rev[24], fw_rev[24];
417 	off_t set3size;
418 	int inst, i;
419 	int sm_hba = 1;
420 	int protocol = 0;
421 	int num_phys = 0;
422 	pmcs_hw_t *pwp;
423 	pmcs_phy_t *phyp;
424 	uint32_t num_threads;
425 	char buf[64];
426 
427 	switch (cmd) {
428 	case DDI_ATTACH:
429 		break;
430 
431 	case DDI_PM_RESUME:
432 	case DDI_RESUME:
433 		tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
434 		if (!tran) {
435 			return (DDI_FAILURE);
436 		}
437 		/* No DDI_?_RESUME on iport nodes */
438 		if (scsi_hba_iport_unit_address(dip) != NULL) {
439 			return (DDI_SUCCESS);
440 		}
441 		pwp = TRAN2PMC(tran);
442 		if (pwp == NULL) {
443 			return (DDI_FAILURE);
444 		}
445 
446 		mutex_enter(&pwp->lock);
447 		pwp->suspended = 0;
448 		if (pwp->tq) {
449 			ddi_taskq_resume(pwp->tq);
450 		}
451 		mutex_exit(&pwp->lock);
452 		return (DDI_SUCCESS);
453 
454 	default:
455 		return (DDI_FAILURE);
456 	}
457 
458 	/*
459 	 * If this is an iport node, invoke iport attach.
460 	 */
461 	if (scsi_hba_iport_unit_address(dip) != NULL) {
462 		return (pmcs_iport_attach(dip));
463 	}
464 
465 	/*
466 	 * From here on is attach for the HBA node
467 	 */
468 
469 #ifdef	DEBUG
470 	/*
471 	 * Check to see if this unit is to be disabled.  We can't disable
472 	 * on a per-iport node.  It's either the entire HBA or nothing.
473 	 */
474 	(void) snprintf(buf, sizeof (buf),
475 	    "disable-instance-%d", ddi_get_instance(dip));
476 	if (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
477 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, buf, 0)) {
478 		cmn_err(CE_NOTE, "pmcs%d: disabled by configuration",
479 		    ddi_get_instance(dip));
480 		return (DDI_FAILURE);
481 	}
482 #endif
483 
484 	/*
485 	 * Allocate softstate
486 	 */
487 	inst = ddi_get_instance(dip);
488 	if (ddi_soft_state_zalloc(pmcs_softc_state, inst) != DDI_SUCCESS) {
489 		cmn_err(CE_WARN, "pmcs%d: Failed to alloc soft state", inst);
490 		return (DDI_FAILURE);
491 	}
492 
493 	pwp = ddi_get_soft_state(pmcs_softc_state, inst);
494 	if (pwp == NULL) {
495 		cmn_err(CE_WARN, "pmcs%d: cannot get soft state", inst);
496 		ddi_soft_state_free(pmcs_softc_state, inst);
497 		return (DDI_FAILURE);
498 	}
499 	pwp->dip = dip;
500 	STAILQ_INIT(&pwp->dq);
501 	STAILQ_INIT(&pwp->cq);
502 	STAILQ_INIT(&pwp->wf);
503 	STAILQ_INIT(&pwp->pf);
504 	/*
505 	 * Create the list for iports
506 	 */
507 	list_create(&pwp->iports, sizeof (pmcs_iport_t),
508 	    offsetof(pmcs_iport_t, list_node));
509 
510 	pwp->state = STATE_PROBING;
511 
512 	/*
513 	 * Get driver.conf properties
514 	 */
515 	pwp->debug_mask = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
516 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-debug-mask",
517 	    debug_mask);
518 	pwp->phyid_block_mask = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
519 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-phyid-block-mask",
520 	    block_mask);
521 	pwp->physpeed = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
522 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-physpeed", physpeed);
523 	pwp->phymode = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
524 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-phymode", phymode);
525 	pwp->fwlog = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
526 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-fwlog", fwlog_level);
527 	if (pwp->fwlog > PMCS_FWLOG_MAX) {
528 		pwp->fwlog = PMCS_FWLOG_MAX;
529 	}
530 
531 	mutex_enter(&pmcs_trace_lock);
532 	if (pmcs_tbuf == NULL) {
533 		/* Allocate trace buffer */
534 		pmcs_tbuf_num_elems = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
535 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-tbuf-num-elems",
536 		    PMCS_TBUF_NUM_ELEMS_DEF);
537 		if ((pmcs_tbuf_num_elems == DDI_PROP_NOT_FOUND) ||
538 		    (pmcs_tbuf_num_elems == 0)) {
539 			pmcs_tbuf_num_elems = PMCS_TBUF_NUM_ELEMS_DEF;
540 		}
541 
542 		pmcs_tbuf = kmem_zalloc(pmcs_tbuf_num_elems *
543 		    sizeof (pmcs_tbuf_t), KM_SLEEP);
544 		pmcs_tbuf_ptr = pmcs_tbuf;
545 		pmcs_tbuf_idx = 0;
546 	}
547 	mutex_exit(&pmcs_trace_lock);
548 
549 	disable_msix = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
550 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-disable-msix",
551 	    disable_msix);
552 	disable_msi = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
553 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-disable-msi",
554 	    disable_msi);
555 	maxqdepth = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
556 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-maxqdepth", maxqdepth);
557 	pwp->fw_force_update = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
558 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-fw-force-update", 0);
559 	if (pwp->fw_force_update == 0) {
560 		pwp->fw_disable_update = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
561 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
562 		    "pmcs-fw-disable-update", 0);
563 	}
564 	pwp->ioq_depth = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
565 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-num-io-qentries",
566 	    PMCS_NQENTRY);
567 
568 	/*
569 	 * Initialize FMA
570 	 */
571 	pwp->dev_acc_attr = pwp->reg_acc_attr = rattr;
572 	pwp->iqp_dma_attr = pwp->oqp_dma_attr =
573 	    pwp->regdump_dma_attr = pwp->cip_dma_attr =
574 	    pwp->fwlog_dma_attr = pmcs_dattr;
575 	pwp->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, pwp->dip,
576 	    DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "fm-capable",
577 	    DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
578 	    DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
579 	pmcs_fm_init(pwp);
580 
581 	/*
582 	 * Map registers
583 	 */
584 	if (pci_config_setup(dip, &pwp->pci_acc_handle)) {
585 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
586 		    "pci config setup failed");
587 		ddi_soft_state_free(pmcs_softc_state, inst);
588 		return (DDI_FAILURE);
589 	}
590 
591 	/*
592 	 * Get the size of register set 3.
593 	 */
594 	if (ddi_dev_regsize(dip, PMCS_REGSET_3, &set3size) != DDI_SUCCESS) {
595 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
596 		    "unable to get size of register set %d", PMCS_REGSET_3);
597 		pci_config_teardown(&pwp->pci_acc_handle);
598 		ddi_soft_state_free(pmcs_softc_state, inst);
599 		return (DDI_FAILURE);
600 	}
601 
602 	/*
603 	 * Map registers
604 	 */
605 	pwp->reg_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
606 
607 	if (ddi_regs_map_setup(dip, PMCS_REGSET_0, (caddr_t *)&pwp->msg_regs,
608 	    0, 0, &pwp->reg_acc_attr, &pwp->msg_acc_handle)) {
609 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
610 		    "failed to map Message Unit registers");
611 		pci_config_teardown(&pwp->pci_acc_handle);
612 		ddi_soft_state_free(pmcs_softc_state, inst);
613 		return (DDI_FAILURE);
614 	}
615 
616 	if (ddi_regs_map_setup(dip, PMCS_REGSET_1, (caddr_t *)&pwp->top_regs,
617 	    0, 0, &pwp->reg_acc_attr, &pwp->top_acc_handle)) {
618 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
619 		    "failed to map TOP registers");
620 		ddi_regs_map_free(&pwp->msg_acc_handle);
621 		pci_config_teardown(&pwp->pci_acc_handle);
622 		ddi_soft_state_free(pmcs_softc_state, inst);
623 		return (DDI_FAILURE);
624 	}
625 
626 	if (ddi_regs_map_setup(dip, PMCS_REGSET_2, (caddr_t *)&pwp->gsm_regs,
627 	    0, 0, &pwp->reg_acc_attr, &pwp->gsm_acc_handle)) {
628 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
629 		    "failed to map GSM registers");
630 		ddi_regs_map_free(&pwp->top_acc_handle);
631 		ddi_regs_map_free(&pwp->msg_acc_handle);
632 		pci_config_teardown(&pwp->pci_acc_handle);
633 		ddi_soft_state_free(pmcs_softc_state, inst);
634 		return (DDI_FAILURE);
635 	}
636 
637 	if (ddi_regs_map_setup(dip, PMCS_REGSET_3, (caddr_t *)&pwp->mpi_regs,
638 	    0, 0, &pwp->reg_acc_attr, &pwp->mpi_acc_handle)) {
639 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
640 		    "failed to map MPI registers");
641 		ddi_regs_map_free(&pwp->top_acc_handle);
642 		ddi_regs_map_free(&pwp->gsm_acc_handle);
643 		ddi_regs_map_free(&pwp->msg_acc_handle);
644 		pci_config_teardown(&pwp->pci_acc_handle);
645 		ddi_soft_state_free(pmcs_softc_state, inst);
646 		return (DDI_FAILURE);
647 	}
648 	pwp->mpibar =
649 	    (((5U << 2) + 0x10) << PMCS_MSGU_MPI_BAR_SHIFT) | set3size;
650 
651 	/*
652 	 * Make sure we can support this card.
653 	 */
654 	pwp->chiprev = pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION);
655 
656 	switch (pwp->chiprev) {
657 	case PMCS_PM8001_REV_A:
658 	case PMCS_PM8001_REV_B:
659 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
660 		    "Rev A/B Card no longer supported");
661 		goto failure;
662 	case PMCS_PM8001_REV_C:
663 		break;
664 	default:
665 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
666 		    "Unknown chip revision (%d)", pwp->chiprev);
667 		goto failure;
668 	}
669 
670 	/*
671 	 * Allocate DMA addressable area for Inbound and Outbound Queue indices
672 	 * that the chip needs to access plus a space for scratch usage
673 	 */
674 	pwp->cip_dma_attr.dma_attr_align = sizeof (uint32_t);
675 	if (pmcs_dma_setup(pwp, &pwp->cip_dma_attr, &pwp->cip_acchdls,
676 	    &pwp->cip_handles, ptob(1), (caddr_t *)&pwp->cip,
677 	    &pwp->ciaddr) == B_FALSE) {
678 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
679 		    "Failed to setup DMA for index/scratch");
680 		goto failure;
681 	}
682 
683 	bzero(pwp->cip, ptob(1));
684 	pwp->scratch = &pwp->cip[PMCS_INDICES_SIZE];
685 	pwp->scratch_dma = pwp->ciaddr + PMCS_INDICES_SIZE;
686 
687 	/*
688 	 * Allocate DMA S/G list chunks
689 	 */
690 	(void) pmcs_add_more_chunks(pwp, ptob(1) * PMCS_MIN_CHUNK_PAGES);
691 
692 	/*
693 	 * Allocate a DMA addressable area for the firmware log (if needed)
694 	 */
695 	if (pwp->fwlog) {
696 		/*
697 		 * Align to event log header and entry size
698 		 */
699 		pwp->fwlog_dma_attr.dma_attr_align = 32;
700 		if (pmcs_dma_setup(pwp, &pwp->fwlog_dma_attr,
701 		    &pwp->fwlog_acchdl,
702 		    &pwp->fwlog_hndl, PMCS_FWLOG_SIZE,
703 		    (caddr_t *)&pwp->fwlogp,
704 		    &pwp->fwaddr) == B_FALSE) {
705 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
706 			    "Failed to setup DMA for fwlog area");
707 			pwp->fwlog = 0;
708 		} else {
709 			bzero(pwp->fwlogp, PMCS_FWLOG_SIZE);
710 		}
711 	}
712 
713 	if (pwp->flash_chunk_addr == NULL) {
714 		pwp->regdump_dma_attr.dma_attr_align = PMCS_FLASH_CHUNK_SIZE;
715 		if (pmcs_dma_setup(pwp, &pwp->regdump_dma_attr,
716 		    &pwp->regdump_acchdl,
717 		    &pwp->regdump_hndl, PMCS_FLASH_CHUNK_SIZE,
718 		    (caddr_t *)&pwp->flash_chunkp, &pwp->flash_chunk_addr) ==
719 		    B_FALSE) {
720 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
721 			    "Failed to setup DMA for register dump area");
722 			goto failure;
723 		}
724 		bzero(pwp->flash_chunkp, PMCS_FLASH_CHUNK_SIZE);
725 	}
726 
727 	/*
728 	 * More bits of local initialization...
729 	 */
730 	pwp->tq = ddi_taskq_create(dip, "_tq", 4, TASKQ_DEFAULTPRI, 0);
731 	if (pwp->tq == NULL) {
732 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
733 		    "unable to create worker taskq");
734 		goto failure;
735 	}
736 
737 	/*
738 	 * Cache of structures for dealing with I/O completion callbacks.
739 	 */
740 	(void) snprintf(buf, sizeof (buf), "pmcs_iocomp_cb_cache%d", inst);
741 	pwp->iocomp_cb_cache = kmem_cache_create(buf,
742 	    sizeof (pmcs_iocomp_cb_t), 16, NULL, NULL, NULL, NULL, NULL, 0);
743 
744 	/*
745 	 * Cache of PHY structures
746 	 */
747 	(void) snprintf(buf, sizeof (buf), "pmcs_phy_cache%d", inst);
748 	pwp->phy_cache = kmem_cache_create(buf, sizeof (pmcs_phy_t), 8,
749 	    pmcs_phy_constructor, pmcs_phy_destructor, NULL, (void *)pwp,
750 	    NULL, 0);
751 
752 	/*
753 	 * Allocate space for the I/O completion threads
754 	 */
755 	num_threads = ncpus_online;
756 	if (num_threads > PMCS_MAX_CQ_THREADS) {
757 		num_threads = PMCS_MAX_CQ_THREADS;
758 	}
759 
760 	pwp->cq_info.cq_thr_info = kmem_zalloc(sizeof (pmcs_cq_thr_info_t) *
761 	    num_threads, KM_SLEEP);
762 	pwp->cq_info.cq_threads = num_threads;
763 	pwp->cq_info.cq_next_disp_thr = 0;
764 	pwp->cq_info.cq_stop = B_FALSE;
765 
766 	/*
767 	 * Set the quantum value in clock ticks for the I/O interrupt
768 	 * coalescing timer.
769 	 */
770 	pwp->io_intr_coal.quantum = drv_usectohz(PMCS_QUANTUM_TIME_USECS);
771 
772 	/*
773 	 * We have a delicate dance here. We need to set up
774 	 * interrupts so we know how to set up some OQC
775 	 * tables. However, while we're setting up table
776 	 * access, we may need to flash new firmware and
777 	 * reset the card, which will take some finessing.
778 	 */
779 
780 	/*
781 	 * Set up interrupts here.
782 	 */
783 	switch (pmcs_setup_intr(pwp)) {
784 	case 0:
785 		break;
786 	case EIO:
787 		pwp->stuck = 1;
788 		/* FALLTHROUGH */
789 	default:
790 		goto failure;
791 	}
792 
793 	/*
794 	 * Set these up now becuase they are used to initialize the OQC tables.
795 	 *
796 	 * If we have MSI or MSI-X interrupts set up and we have enough
797 	 * vectors for each OQ, the Outbound Queue vectors can all be the
798 	 * same as the appropriate interrupt routine will have been called
799 	 * and the doorbell register automatically cleared.
800 	 * This keeps us from having to check the Outbound Doorbell register
801 	 * when the routines for these interrupts are called.
802 	 *
803 	 * If we have Legacy INT-X interrupts set up or we didn't have enough
804 	 * MSI/MSI-X vectors to uniquely identify each OQ, we point these
805 	 * vectors to the bits we would like to have set in the Outbound
806 	 * Doorbell register because pmcs_all_intr will read the doorbell
807 	 * register to find out why we have an interrupt and write the
808 	 * corresponding 'clear' bit for that interrupt.
809 	 */
810 
811 	switch (pwp->intr_cnt) {
812 	case 1:
813 		/*
814 		 * Only one vector, so we must check all OQs for MSI.  For
815 		 * INT-X, there's only one vector anyway, so we can just
816 		 * use the outbound queue bits to keep from having to
817 		 * check each queue for each interrupt.
818 		 */
819 		if (pwp->int_type == PMCS_INT_FIXED) {
820 			pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
821 			pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
822 			pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_EVENTS;
823 		} else {
824 			pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
825 			pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_IODONE;
826 			pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_IODONE;
827 		}
828 		break;
829 	case 2:
830 		/* With 2, we can at least isolate IODONE */
831 		pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
832 		pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
833 		pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_GENERAL;
834 		break;
835 	case 4:
836 		/* With 4 vectors, everybody gets one */
837 		pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
838 		pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
839 		pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_EVENTS;
840 		break;
841 	}
842 
843 	/*
844 	 * Do the first part of setup
845 	 */
846 	if (pmcs_setup(pwp)) {
847 		goto failure;
848 	}
849 	pmcs_report_fwversion(pwp);
850 
851 	/*
852 	 * Now do some additonal allocations based upon information
853 	 * gathered during MPI setup.
854 	 */
855 	pwp->root_phys = kmem_zalloc(pwp->nphy * sizeof (pmcs_phy_t), KM_SLEEP);
856 	ASSERT(pwp->nphy < SAS2_PHYNUM_MAX);
857 	phyp = pwp->root_phys;
858 	for (i = 0; i < pwp->nphy; i++) {
859 		if (i < pwp->nphy-1) {
860 			phyp->sibling = (phyp + 1);
861 		}
862 		mutex_init(&phyp->phy_lock, NULL, MUTEX_DRIVER,
863 		    DDI_INTR_PRI(pwp->intr_pri));
864 		phyp->phynum = i & SAS2_PHYNUM_MASK;
865 		pmcs_phy_name(pwp, phyp, phyp->path, sizeof (phyp->path));
866 		phyp->pwp = pwp;
867 		phyp->device_id = PMCS_INVALID_DEVICE_ID;
868 		phyp->portid = PMCS_PHY_INVALID_PORT_ID;
869 		phyp++;
870 	}
871 
872 	pwp->work = kmem_zalloc(pwp->max_cmd * sizeof (pmcwork_t), KM_SLEEP);
873 	for (i = 0; i < pwp->max_cmd - 1; i++) {
874 		pmcwork_t *pwrk = &pwp->work[i];
875 		mutex_init(&pwrk->lock, NULL, MUTEX_DRIVER,
876 		    DDI_INTR_PRI(pwp->intr_pri));
877 		cv_init(&pwrk->sleep_cv, NULL, CV_DRIVER, NULL);
878 		STAILQ_INSERT_TAIL(&pwp->wf, pwrk, next);
879 
880 	}
881 	pwp->targets = (pmcs_xscsi_t **)
882 	    kmem_zalloc(pwp->max_dev * sizeof (pmcs_xscsi_t *), KM_SLEEP);
883 
884 	pwp->iqpt = (pmcs_iqp_trace_t *)
885 	    kmem_zalloc(sizeof (pmcs_iqp_trace_t), KM_SLEEP);
886 	pwp->iqpt->head = kmem_zalloc(PMCS_IQP_TRACE_BUFFER_SIZE, KM_SLEEP);
887 	pwp->iqpt->curpos = pwp->iqpt->head;
888 	pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE;
889 
890 	/*
891 	 * Start MPI communication.
892 	 */
893 	if (pmcs_start_mpi(pwp)) {
894 		if (pmcs_soft_reset(pwp, B_FALSE)) {
895 			goto failure;
896 		}
897 		pwp->last_reset_reason = PMCS_LAST_RST_ATTACH;
898 	}
899 
900 	/*
901 	 * Do some initial acceptance tests.
902 	 * This tests interrupts and queues.
903 	 */
904 	if (pmcs_echo_test(pwp)) {
905 		goto failure;
906 	}
907 
908 	/* Read VPD - if it exists */
909 	if (pmcs_get_nvmd(pwp, PMCS_NVMD_VPD, PMCIN_NVMD_VPD, 0, NULL, 0)) {
910 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
911 		    "%s: Unable to read VPD: "
912 		    "attempting to fabricate", __func__);
913 		/*
914 		 * When we release, this must goto failure and the call
915 		 * to pmcs_fabricate_wwid is removed.
916 		 */
917 		/* goto failure; */
918 		if (!pmcs_fabricate_wwid(pwp)) {
919 			goto failure;
920 		}
921 	}
922 
923 	/*
924 	 * We're now officially running
925 	 */
926 	pwp->state = STATE_RUNNING;
927 
928 	/*
929 	 * Check firmware versions and load new firmware
930 	 * if needed and reset.
931 	 */
932 	if (pmcs_firmware_update(pwp)) {
933 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
934 		    "%s: Firmware update failed", __func__);
935 		goto failure;
936 	}
937 
938 	/*
939 	 * Create completion threads.
940 	 */
941 	for (i = 0; i < pwp->cq_info.cq_threads; i++) {
942 		pwp->cq_info.cq_thr_info[i].cq_pwp = pwp;
943 		pwp->cq_info.cq_thr_info[i].cq_thread =
944 		    thread_create(NULL, 0, pmcs_scsa_cq_run,
945 		    &pwp->cq_info.cq_thr_info[i], 0, &p0, TS_RUN, minclsyspri);
946 	}
947 
948 	/*
949 	 * Create one thread to deal with the updating of the interrupt
950 	 * coalescing timer.
951 	 */
952 	pwp->ict_thread = thread_create(NULL, 0, pmcs_check_intr_coal,
953 	    pwp, 0, &p0, TS_RUN, minclsyspri);
954 
955 	/*
956 	 * Kick off the watchdog
957 	 */
958 	pwp->wdhandle = timeout(pmcs_watchdog, pwp,
959 	    drv_usectohz(PMCS_WATCH_INTERVAL));
960 	/*
961 	 * Do the SCSI attachment code (before starting phys)
962 	 */
963 	if (pmcs_scsa_init(pwp, &pmcs_dattr)) {
964 		goto failure;
965 	}
966 	pwp->hba_attached = 1;
967 
968 	/*
969 	 * Initialize the rwlock for the iport elements.
970 	 */
971 	rw_init(&pwp->iports_lock, NULL, RW_DRIVER, NULL);
972 
973 	/* Check all acc & dma handles allocated in attach */
974 	if (pmcs_check_acc_dma_handle(pwp)) {
975 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
976 		goto failure;
977 	}
978 
979 	/*
980 	 * Create the phymap for this HBA instance
981 	 */
982 	if (sas_phymap_create(dip, phymap_usec, PHYMAP_MODE_SIMPLE, NULL,
983 	    pwp, pmcs_phymap_activate, pmcs_phymap_deactivate,
984 	    &pwp->hss_phymap) != DDI_SUCCESS) {
985 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
986 		    "%s: pmcs%d phymap_create failed", __func__, inst);
987 		goto failure;
988 	}
989 	ASSERT(pwp->hss_phymap);
990 
991 	/*
992 	 * Create the iportmap for this HBA instance
993 	 */
994 	if (scsi_hba_iportmap_create(dip, iportmap_usec,
995 	    &pwp->hss_iportmap) != DDI_SUCCESS) {
996 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
997 		    "%s: pmcs%d iportmap_create failed", __func__, inst);
998 		goto failure;
999 	}
1000 	ASSERT(pwp->hss_iportmap);
1001 
1002 	/*
1003 	 * Start the PHYs.
1004 	 */
1005 	if (pmcs_start_phys(pwp)) {
1006 		goto failure;
1007 	}
1008 
1009 	/*
1010 	 * From this point on, we can't fail.
1011 	 */
1012 	ddi_report_dev(dip);
1013 
1014 	/* SM-HBA */
1015 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_SMHBA_SUPPORTED,
1016 	    &sm_hba);
1017 
1018 	/* SM-HBA */
1019 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_DRV_VERSION,
1020 	    pmcs_driver_rev);
1021 
1022 	/* SM-HBA */
1023 	chiprev = 'A' + pwp->chiprev;
1024 	(void) snprintf(hw_rev, 2, "%s", &chiprev);
1025 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_HWARE_VERSION,
1026 	    hw_rev);
1027 
1028 	/* SM-HBA */
1029 	switch (PMCS_FW_TYPE(pwp)) {
1030 	case PMCS_FW_TYPE_RELEASED:
1031 		fwsupport = "Released";
1032 		break;
1033 	case PMCS_FW_TYPE_DEVELOPMENT:
1034 		fwsupport = "Development";
1035 		break;
1036 	case PMCS_FW_TYPE_ALPHA:
1037 		fwsupport = "Alpha";
1038 		break;
1039 	case PMCS_FW_TYPE_BETA:
1040 		fwsupport = "Beta";
1041 		break;
1042 	default:
1043 		fwsupport = "Special";
1044 		break;
1045 	}
1046 	(void) snprintf(fw_rev, sizeof (fw_rev), "%x.%x.%x %s",
1047 	    PMCS_FW_MAJOR(pwp), PMCS_FW_MINOR(pwp), PMCS_FW_MICRO(pwp),
1048 	    fwsupport);
1049 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_FWARE_VERSION,
1050 	    fw_rev);
1051 
1052 	/* SM-HBA */
1053 	num_phys = pwp->nphy;
1054 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_NUM_PHYS_HBA,
1055 	    &num_phys);
1056 
1057 	/* SM-HBA */
1058 	protocol = SAS_SSP_SUPPORT | SAS_SATA_SUPPORT | SAS_SMP_SUPPORT;
1059 	pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_SUPPORTED_PROTOCOL,
1060 	    &protocol);
1061 
1062 	return (DDI_SUCCESS);
1063 
1064 failure:
1065 	if (pmcs_unattach(pwp)) {
1066 		pwp->stuck = 1;
1067 	}
1068 	return (DDI_FAILURE);
1069 }
1070 
1071 int
1072 pmcs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1073 {
1074 	int inst = ddi_get_instance(dip);
1075 	pmcs_iport_t	*iport = NULL;
1076 	pmcs_hw_t	*pwp = NULL;
1077 	scsi_hba_tran_t	*tran;
1078 
1079 	if (scsi_hba_iport_unit_address(dip) != NULL) {
1080 		/* iport node */
1081 		iport = ddi_get_soft_state(pmcs_iport_softstate, inst);
1082 		ASSERT(iport);
1083 		if (iport == NULL) {
1084 			return (DDI_FAILURE);
1085 		}
1086 		pwp = iport->pwp;
1087 	} else {
1088 		/* hba node */
1089 		pwp = (pmcs_hw_t *)ddi_get_soft_state(pmcs_softc_state, inst);
1090 		ASSERT(pwp);
1091 		if (pwp == NULL) {
1092 			return (DDI_FAILURE);
1093 		}
1094 	}
1095 
1096 	switch (cmd) {
1097 	case DDI_DETACH:
1098 		if (iport) {
1099 			/* iport detach */
1100 			if (pmcs_iport_unattach(iport)) {
1101 				return (DDI_FAILURE);
1102 			}
1103 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1104 			    "iport%d detached", inst);
1105 			return (DDI_SUCCESS);
1106 		} else {
1107 			/* HBA detach */
1108 			if (pmcs_unattach(pwp)) {
1109 				return (DDI_FAILURE);
1110 			}
1111 			return (DDI_SUCCESS);
1112 		}
1113 
1114 	case DDI_SUSPEND:
1115 	case DDI_PM_SUSPEND:
1116 		/* No DDI_SUSPEND on iport nodes */
1117 		if (iport) {
1118 			return (DDI_SUCCESS);
1119 		}
1120 
1121 		if (pwp->stuck) {
1122 			return (DDI_FAILURE);
1123 		}
1124 		tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
1125 		if (!tran) {
1126 			return (DDI_FAILURE);
1127 		}
1128 
1129 		pwp = TRAN2PMC(tran);
1130 		if (pwp == NULL) {
1131 			return (DDI_FAILURE);
1132 		}
1133 		mutex_enter(&pwp->lock);
1134 		if (pwp->tq) {
1135 			ddi_taskq_suspend(pwp->tq);
1136 		}
1137 		pwp->suspended = 1;
1138 		mutex_exit(&pwp->lock);
1139 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "PMC8X6G suspending");
1140 		return (DDI_SUCCESS);
1141 
1142 	default:
1143 		return (DDI_FAILURE);
1144 	}
1145 }
1146 
1147 static int
1148 pmcs_iport_unattach(pmcs_iport_t *iport)
1149 {
1150 	pmcs_hw_t	*pwp = iport->pwp;
1151 
1152 	/*
1153 	 * First, check if there are still any configured targets on this
1154 	 * iport.  If so, we fail detach.
1155 	 */
1156 	if (pmcs_iport_has_targets(pwp, iport)) {
1157 		pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
1158 		    "iport%d detach failure: iport has targets (luns)",
1159 		    ddi_get_instance(iport->dip));
1160 		return (DDI_FAILURE);
1161 	}
1162 
1163 	/*
1164 	 * Remove this iport from our list if it is inactive in the phymap.
1165 	 */
1166 	rw_enter(&pwp->iports_lock, RW_WRITER);
1167 	mutex_enter(&iport->lock);
1168 
1169 	if (iport->ua_state == UA_ACTIVE) {
1170 		mutex_exit(&iport->lock);
1171 		rw_exit(&pwp->iports_lock);
1172 		pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
1173 		    "iport%d detach failure: "
1174 		    "iport unit address active in phymap",
1175 		    ddi_get_instance(iport->dip));
1176 		return (DDI_FAILURE);
1177 	}
1178 
1179 	/* If it's our only iport, clear iports_attached */
1180 	ASSERT(pwp->num_iports >= 1);
1181 	if (--pwp->num_iports == 0) {
1182 		pwp->iports_attached = 0;
1183 	}
1184 
1185 	ASSERT(list_link_active(&iport->list_node));
1186 	list_remove(&pwp->iports, iport);
1187 	rw_exit(&pwp->iports_lock);
1188 
1189 	/*
1190 	 * We have removed the iport handle from the HBA's iports list,
1191 	 * there will be no new references to it. Two things must be
1192 	 * guarded against here.  First, we could have PHY up events,
1193 	 * adding themselves to the iport->phys list and grabbing ref's
1194 	 * on our iport handle.  Second, we could have existing references
1195 	 * to this iport handle from a point in time prior to the list
1196 	 * removal above.
1197 	 *
1198 	 * So first, destroy the phys list. Remove any phys that have snuck
1199 	 * in after the phymap deactivate, dropping the refcnt accordingly.
1200 	 * If these PHYs are still up if and when the phymap reactivates
1201 	 * (i.e. when this iport reattaches), we'll populate the list with
1202 	 * them and bump the refcnt back up.
1203 	 */
1204 	pmcs_remove_phy_from_iport(iport, NULL);
1205 	ASSERT(list_is_empty(&iport->phys));
1206 	list_destroy(&iport->phys);
1207 	mutex_exit(&iport->lock);
1208 
1209 	/*
1210 	 * Second, wait for any other references to this iport to be
1211 	 * dropped, then continue teardown.
1212 	 */
1213 	mutex_enter(&iport->refcnt_lock);
1214 	while (iport->refcnt != 0) {
1215 		cv_wait(&iport->refcnt_cv, &iport->refcnt_lock);
1216 	}
1217 	mutex_exit(&iport->refcnt_lock);
1218 
1219 	/* Delete kstats */
1220 	pmcs_destroy_phy_stats(iport);
1221 
1222 	/* Destroy the iport target map */
1223 	if (pmcs_iport_tgtmap_destroy(iport) == B_FALSE) {
1224 		return (DDI_FAILURE);
1225 	}
1226 
1227 	/* Free the tgt soft state */
1228 	if (iport->tgt_sstate != NULL) {
1229 		ddi_soft_state_bystr_fini(&iport->tgt_sstate);
1230 	}
1231 
1232 	/* Free our unit address string */
1233 	strfree(iport->ua);
1234 
1235 	/* Finish teardown and free the softstate */
1236 	mutex_destroy(&iport->refcnt_lock);
1237 	mutex_destroy(&iport->smp_lock);
1238 	ASSERT(iport->refcnt == 0);
1239 	cv_destroy(&iport->refcnt_cv);
1240 	cv_destroy(&iport->smp_cv);
1241 	mutex_destroy(&iport->lock);
1242 	ddi_soft_state_free(pmcs_iport_softstate, ddi_get_instance(iport->dip));
1243 
1244 	return (DDI_SUCCESS);
1245 }
1246 
1247 static int
1248 pmcs_unattach(pmcs_hw_t *pwp)
1249 {
1250 	int i;
1251 	enum pwpstate curstate;
1252 	pmcs_cq_thr_info_t *cqti;
1253 
1254 	/*
1255 	 * Tear down the interrupt infrastructure.
1256 	 */
1257 	if (pmcs_teardown_intr(pwp)) {
1258 		pwp->stuck = 1;
1259 	}
1260 	pwp->intr_cnt = 0;
1261 
1262 	/*
1263 	 * Grab a lock, if initted, to set state.
1264 	 */
1265 	if (pwp->locks_initted) {
1266 		mutex_enter(&pwp->lock);
1267 		if (pwp->state != STATE_DEAD) {
1268 			pwp->state = STATE_UNPROBING;
1269 		}
1270 		curstate = pwp->state;
1271 		mutex_exit(&pwp->lock);
1272 
1273 		/*
1274 		 * Stop the I/O completion threads.
1275 		 */
1276 		mutex_enter(&pwp->cq_lock);
1277 		pwp->cq_info.cq_stop = B_TRUE;
1278 		for (i = 0; i < pwp->cq_info.cq_threads; i++) {
1279 			if (pwp->cq_info.cq_thr_info[i].cq_thread) {
1280 				cqti = &pwp->cq_info.cq_thr_info[i];
1281 				mutex_enter(&cqti->cq_thr_lock);
1282 				cv_signal(&cqti->cq_cv);
1283 				mutex_exit(&cqti->cq_thr_lock);
1284 				mutex_exit(&pwp->cq_lock);
1285 				thread_join(cqti->cq_thread->t_did);
1286 				mutex_enter(&pwp->cq_lock);
1287 			}
1288 		}
1289 		mutex_exit(&pwp->cq_lock);
1290 
1291 		/*
1292 		 * Stop the interrupt coalescing timer thread
1293 		 */
1294 		if (pwp->ict_thread) {
1295 			mutex_enter(&pwp->ict_lock);
1296 			pwp->io_intr_coal.stop_thread = B_TRUE;
1297 			cv_signal(&pwp->ict_cv);
1298 			mutex_exit(&pwp->ict_lock);
1299 			thread_join(pwp->ict_thread->t_did);
1300 		}
1301 	} else {
1302 		if (pwp->state != STATE_DEAD) {
1303 			pwp->state = STATE_UNPROBING;
1304 		}
1305 		curstate = pwp->state;
1306 	}
1307 
1308 	if (&pwp->iports != NULL) {
1309 		/* Destroy the iports lock */
1310 		rw_destroy(&pwp->iports_lock);
1311 		/* Destroy the iports list */
1312 		ASSERT(list_is_empty(&pwp->iports));
1313 		list_destroy(&pwp->iports);
1314 	}
1315 
1316 	if (pwp->hss_iportmap != NULL) {
1317 		/* Destroy the iportmap */
1318 		scsi_hba_iportmap_destroy(pwp->hss_iportmap);
1319 	}
1320 
1321 	if (pwp->hss_phymap != NULL) {
1322 		/* Destroy the phymap */
1323 		sas_phymap_destroy(pwp->hss_phymap);
1324 	}
1325 
1326 	/*
1327 	 * Make sure that any pending watchdog won't
1328 	 * be called from this point on out.
1329 	 */
1330 	(void) untimeout(pwp->wdhandle);
1331 	/*
1332 	 * After the above action, the watchdog
1333 	 * timer that starts up the worker task
1334 	 * may trigger but will exit immediately
1335 	 * on triggering.
1336 	 *
1337 	 * Now that this is done, we can destroy
1338 	 * the task queue, which will wait if we're
1339 	 * running something on it.
1340 	 */
1341 	if (pwp->tq) {
1342 		ddi_taskq_destroy(pwp->tq);
1343 		pwp->tq = NULL;
1344 	}
1345 
1346 	pmcs_fm_fini(pwp);
1347 
1348 	if (pwp->hba_attached) {
1349 		(void) scsi_hba_detach(pwp->dip);
1350 		pwp->hba_attached = 0;
1351 	}
1352 
1353 	/*
1354 	 * If the chip hasn't been marked dead, shut it down now
1355 	 * to bring it back to a known state without attempting
1356 	 * a soft reset.
1357 	 */
1358 	if (curstate != STATE_DEAD && pwp->locks_initted) {
1359 		/*
1360 		 * De-register all registered devices
1361 		 */
1362 		pmcs_deregister_devices(pwp, pwp->root_phys);
1363 
1364 		/*
1365 		 * Stop all the phys.
1366 		 */
1367 		pmcs_stop_phys(pwp);
1368 
1369 		/*
1370 		 * Shut Down Message Passing
1371 		 */
1372 		(void) pmcs_stop_mpi(pwp);
1373 
1374 		/*
1375 		 * Reset chip
1376 		 */
1377 		(void) pmcs_soft_reset(pwp, B_FALSE);
1378 		pwp->last_reset_reason = PMCS_LAST_RST_DETACH;
1379 	}
1380 
1381 	/*
1382 	 * Turn off interrupts on the chip
1383 	 */
1384 	if (pwp->mpi_acc_handle) {
1385 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
1386 	}
1387 
1388 	/* Destroy pwp's lock */
1389 	if (pwp->locks_initted) {
1390 		mutex_destroy(&pwp->lock);
1391 		mutex_destroy(&pwp->dma_lock);
1392 		mutex_destroy(&pwp->axil_lock);
1393 		mutex_destroy(&pwp->cq_lock);
1394 		mutex_destroy(&pwp->config_lock);
1395 		mutex_destroy(&pwp->ict_lock);
1396 		mutex_destroy(&pwp->wfree_lock);
1397 		mutex_destroy(&pwp->pfree_lock);
1398 		mutex_destroy(&pwp->dead_phylist_lock);
1399 #ifdef	DEBUG
1400 		mutex_destroy(&pwp->dbglock);
1401 #endif
1402 		cv_destroy(&pwp->ict_cv);
1403 		cv_destroy(&pwp->drain_cv);
1404 		pwp->locks_initted = 0;
1405 	}
1406 
1407 	/*
1408 	 * Free DMA handles and associated consistent memory
1409 	 */
1410 	if (pwp->regdump_hndl) {
1411 		if (ddi_dma_unbind_handle(pwp->regdump_hndl) != DDI_SUCCESS) {
1412 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1413 			    "Condition check failed "
1414 			    "at %s():%d", __func__, __LINE__);
1415 		}
1416 		ddi_dma_free_handle(&pwp->regdump_hndl);
1417 		ddi_dma_mem_free(&pwp->regdump_acchdl);
1418 		pwp->regdump_hndl = 0;
1419 	}
1420 	if (pwp->fwlog_hndl) {
1421 		if (ddi_dma_unbind_handle(pwp->fwlog_hndl) != DDI_SUCCESS) {
1422 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1423 			    "Condition check failed "
1424 			    "at %s():%d", __func__, __LINE__);
1425 		}
1426 		ddi_dma_free_handle(&pwp->fwlog_hndl);
1427 		ddi_dma_mem_free(&pwp->fwlog_acchdl);
1428 		pwp->fwlog_hndl = 0;
1429 	}
1430 	if (pwp->cip_handles) {
1431 		if (ddi_dma_unbind_handle(pwp->cip_handles) != DDI_SUCCESS) {
1432 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1433 			    "Condition check failed "
1434 			    "at %s():%d", __func__, __LINE__);
1435 		}
1436 		ddi_dma_free_handle(&pwp->cip_handles);
1437 		ddi_dma_mem_free(&pwp->cip_acchdls);
1438 		pwp->cip_handles = 0;
1439 	}
1440 	for (i = 0; i < PMCS_NOQ; i++) {
1441 		if (pwp->oqp_handles[i]) {
1442 			if (ddi_dma_unbind_handle(pwp->oqp_handles[i]) !=
1443 			    DDI_SUCCESS) {
1444 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1445 				    "Condition check failed at %s():%d",
1446 				    __func__, __LINE__);
1447 			}
1448 			ddi_dma_free_handle(&pwp->oqp_handles[i]);
1449 			ddi_dma_mem_free(&pwp->oqp_acchdls[i]);
1450 			pwp->oqp_handles[i] = 0;
1451 		}
1452 	}
1453 	for (i = 0; i < PMCS_NIQ; i++) {
1454 		if (pwp->iqp_handles[i]) {
1455 			if (ddi_dma_unbind_handle(pwp->iqp_handles[i]) !=
1456 			    DDI_SUCCESS) {
1457 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1458 				    "Condition check failed at %s():%d",
1459 				    __func__, __LINE__);
1460 			}
1461 			ddi_dma_free_handle(&pwp->iqp_handles[i]);
1462 			ddi_dma_mem_free(&pwp->iqp_acchdls[i]);
1463 			pwp->iqp_handles[i] = 0;
1464 		}
1465 	}
1466 
1467 	pmcs_free_dma_chunklist(pwp);
1468 
1469 	/*
1470 	 * Unmap registers and destroy access handles
1471 	 */
1472 	if (pwp->mpi_acc_handle) {
1473 		ddi_regs_map_free(&pwp->mpi_acc_handle);
1474 		pwp->mpi_acc_handle = 0;
1475 	}
1476 	if (pwp->top_acc_handle) {
1477 		ddi_regs_map_free(&pwp->top_acc_handle);
1478 		pwp->top_acc_handle = 0;
1479 	}
1480 	if (pwp->gsm_acc_handle) {
1481 		ddi_regs_map_free(&pwp->gsm_acc_handle);
1482 		pwp->gsm_acc_handle = 0;
1483 	}
1484 	if (pwp->msg_acc_handle) {
1485 		ddi_regs_map_free(&pwp->msg_acc_handle);
1486 		pwp->msg_acc_handle = 0;
1487 	}
1488 	if (pwp->pci_acc_handle) {
1489 		pci_config_teardown(&pwp->pci_acc_handle);
1490 		pwp->pci_acc_handle = 0;
1491 	}
1492 
1493 	/*
1494 	 * Do memory allocation cleanup.
1495 	 */
1496 	while (pwp->dma_freelist) {
1497 		pmcs_dmachunk_t *this = pwp->dma_freelist;
1498 		pwp->dma_freelist = this->nxt;
1499 		kmem_free(this, sizeof (pmcs_dmachunk_t));
1500 	}
1501 
1502 	/*
1503 	 * Free pools
1504 	 */
1505 	if (pwp->iocomp_cb_cache) {
1506 		kmem_cache_destroy(pwp->iocomp_cb_cache);
1507 	}
1508 
1509 	/*
1510 	 * Free all PHYs (at level > 0), then free the cache
1511 	 */
1512 	pmcs_free_all_phys(pwp, pwp->root_phys);
1513 	if (pwp->phy_cache) {
1514 		kmem_cache_destroy(pwp->phy_cache);
1515 	}
1516 
1517 	/*
1518 	 * Free root PHYs
1519 	 */
1520 	if (pwp->root_phys) {
1521 		pmcs_phy_t *phyp = pwp->root_phys;
1522 		for (i = 0; i < pwp->nphy; i++) {
1523 			mutex_destroy(&phyp->phy_lock);
1524 			phyp = phyp->sibling;
1525 		}
1526 		kmem_free(pwp->root_phys, pwp->nphy * sizeof (pmcs_phy_t));
1527 		pwp->root_phys = NULL;
1528 		pwp->nphy = 0;
1529 	}
1530 
1531 	/* Free the targets list */
1532 	if (pwp->targets) {
1533 		kmem_free(pwp->targets,
1534 		    sizeof (pmcs_xscsi_t *) * pwp->max_dev);
1535 	}
1536 
1537 	/*
1538 	 * Free work structures
1539 	 */
1540 
1541 	if (pwp->work && pwp->max_cmd) {
1542 		for (i = 0; i < pwp->max_cmd - 1; i++) {
1543 			pmcwork_t *pwrk = &pwp->work[i];
1544 			mutex_destroy(&pwrk->lock);
1545 			cv_destroy(&pwrk->sleep_cv);
1546 		}
1547 		kmem_free(pwp->work, sizeof (pmcwork_t) * pwp->max_cmd);
1548 		pwp->work = NULL;
1549 		pwp->max_cmd = 0;
1550 	}
1551 
1552 	/*
1553 	 * Do last property and SCSA cleanup
1554 	 */
1555 	if (pwp->tran) {
1556 		scsi_hba_tran_free(pwp->tran);
1557 		pwp->tran = NULL;
1558 	}
1559 	if (pwp->reset_notify_listf) {
1560 		scsi_hba_reset_notify_tear_down(pwp->reset_notify_listf);
1561 		pwp->reset_notify_listf = NULL;
1562 	}
1563 	ddi_prop_remove_all(pwp->dip);
1564 	if (pwp->stuck) {
1565 		return (-1);
1566 	}
1567 
1568 	/* Free register dump area if allocated */
1569 	if (pwp->regdumpp) {
1570 		kmem_free(pwp->regdumpp, PMCS_REG_DUMP_SIZE);
1571 		pwp->regdumpp = NULL;
1572 	}
1573 	if (pwp->iqpt && pwp->iqpt->head) {
1574 		kmem_free(pwp->iqpt->head, PMCS_IQP_TRACE_BUFFER_SIZE);
1575 		pwp->iqpt->head = pwp->iqpt->curpos = NULL;
1576 	}
1577 	if (pwp->iqpt) {
1578 		kmem_free(pwp->iqpt, sizeof (pmcs_iqp_trace_t));
1579 		pwp->iqpt = NULL;
1580 	}
1581 
1582 	ddi_soft_state_free(pmcs_softc_state, ddi_get_instance(pwp->dip));
1583 	return (0);
1584 }
1585 
1586 /*
1587  * quiesce (9E) entry point
1588  *
1589  * This function is called when the system is single-threaded at high PIL
1590  * with preemption disabled. Therefore, the function must not block/wait/sleep.
1591  *
1592  * Returns DDI_SUCCESS or DDI_FAILURE.
1593  *
1594  */
1595 static int
1596 pmcs_quiesce(dev_info_t *dip)
1597 {
1598 	pmcs_hw_t	*pwp;
1599 	scsi_hba_tran_t	*tran;
1600 
1601 	if ((tran = ddi_get_driver_private(dip)) == NULL)
1602 		return (DDI_SUCCESS);
1603 
1604 	/* No quiesce necessary on a per-iport basis */
1605 	if (scsi_hba_iport_unit_address(dip) != NULL) {
1606 		return (DDI_SUCCESS);
1607 	}
1608 
1609 	if ((pwp = TRAN2PMC(tran)) == NULL)
1610 		return (DDI_SUCCESS);
1611 
1612 	/* Stop MPI & Reset chip (no need to re-initialize) */
1613 	(void) pmcs_stop_mpi(pwp);
1614 	(void) pmcs_soft_reset(pwp, B_TRUE);
1615 	pwp->last_reset_reason = PMCS_LAST_RST_QUIESCE;
1616 
1617 	return (DDI_SUCCESS);
1618 }
1619 
1620 /*
1621  * Called with xp->statlock and PHY lock and scratch acquired.
1622  */
1623 static int
1624 pmcs_add_sata_device(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
1625 {
1626 	ata_identify_t *ati;
1627 	int result, i;
1628 	pmcs_phy_t *pptr;
1629 	uint16_t *a;
1630 	union {
1631 		uint8_t nsa[8];
1632 		uint16_t nsb[4];
1633 	} u;
1634 
1635 	/*
1636 	 * Safe defaults - use only if this target is brand new (i.e. doesn't
1637 	 * already have these settings configured)
1638 	 */
1639 	if (xp->capacity == 0) {
1640 		xp->capacity = (uint64_t)-1;
1641 		xp->ca = 1;
1642 		xp->qdepth = 1;
1643 		xp->pio = 1;
1644 	}
1645 
1646 	pptr = xp->phy;
1647 
1648 	/*
1649 	 * We only try and issue an IDENTIFY for first level
1650 	 * (direct attached) devices. We don't try and
1651 	 * set other quirks here (this will happen later,
1652 	 * if the device is fully configured)
1653 	 */
1654 	if (pptr->level) {
1655 		return (0);
1656 	}
1657 
1658 	mutex_exit(&xp->statlock);
1659 	result = pmcs_sata_identify(pwp, pptr);
1660 	mutex_enter(&xp->statlock);
1661 
1662 	if (result) {
1663 		return (result);
1664 	}
1665 	ati = pwp->scratch;
1666 	a = &ati->word108;
1667 	for (i = 0; i < 4; i++) {
1668 		u.nsb[i] = ddi_swap16(*a++);
1669 	}
1670 
1671 	/*
1672 	 * Check the returned data for being a valid (NAA=5) WWN.
1673 	 * If so, use that and override the SAS address we were
1674 	 * given at Link Up time.
1675 	 */
1676 	if ((u.nsa[0] >> 4) == 5) {
1677 		(void) memcpy(pptr->sas_address, u.nsa, 8);
1678 	}
1679 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
1680 	    "%s: %s has SAS ADDRESS " SAS_ADDR_FMT,
1681 	    __func__, pptr->path, SAS_ADDR_PRT(pptr->sas_address));
1682 	return (0);
1683 }
1684 
1685 /*
1686  * Called with PHY lock and target statlock held and scratch acquired
1687  */
1688 static boolean_t
1689 pmcs_add_new_device(pmcs_hw_t *pwp, pmcs_xscsi_t *target)
1690 {
1691 	ASSERT(target != NULL);
1692 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, target, "%s: target = 0x%p",
1693 	    __func__, (void *) target);
1694 
1695 	switch (target->phy->dtype) {
1696 	case SATA:
1697 		if (pmcs_add_sata_device(pwp, target) != 0) {
1698 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, target->phy,
1699 			    target, "%s: add_sata_device failed for tgt 0x%p",
1700 			    __func__, (void *) target);
1701 			return (B_FALSE);
1702 		}
1703 		break;
1704 	case SAS:
1705 		target->qdepth = maxqdepth;
1706 		break;
1707 	case EXPANDER:
1708 		target->qdepth = 1;
1709 		break;
1710 	}
1711 
1712 	target->new = 0;
1713 	target->assigned = 1;
1714 	target->dev_state = PMCS_DEVICE_STATE_OPERATIONAL;
1715 	target->dtype = target->phy->dtype;
1716 
1717 	/*
1718 	 * Set the PHY's config stop time to 0.  This is one of the final
1719 	 * stops along the config path, so we're indicating that we
1720 	 * successfully configured the PHY.
1721 	 */
1722 	target->phy->config_stop = 0;
1723 
1724 	return (B_TRUE);
1725 }
1726 
1727 void
1728 pmcs_worker(void *arg)
1729 {
1730 	pmcs_hw_t *pwp = arg;
1731 	ulong_t work_flags;
1732 
1733 	DTRACE_PROBE2(pmcs__worker, ulong_t, pwp->work_flags, boolean_t,
1734 	    pwp->config_changed);
1735 
1736 	if (pwp->state != STATE_RUNNING) {
1737 		return;
1738 	}
1739 
1740 	work_flags = atomic_swap_ulong(&pwp->work_flags, 0);
1741 
1742 	if (work_flags & PMCS_WORK_FLAG_SAS_HW_ACK) {
1743 		pmcs_ack_events(pwp);
1744 	}
1745 
1746 	if (work_flags & PMCS_WORK_FLAG_SPINUP_RELEASE) {
1747 		mutex_enter(&pwp->lock);
1748 		pmcs_spinup_release(pwp, NULL);
1749 		mutex_exit(&pwp->lock);
1750 	}
1751 
1752 	if (work_flags & PMCS_WORK_FLAG_SSP_EVT_RECOVERY) {
1753 		pmcs_ssp_event_recovery(pwp);
1754 	}
1755 
1756 	if (work_flags & PMCS_WORK_FLAG_DS_ERR_RECOVERY) {
1757 		pmcs_dev_state_recovery(pwp, NULL);
1758 	}
1759 
1760 	if (work_flags & PMCS_WORK_FLAG_DEREGISTER_DEV) {
1761 		pmcs_deregister_device_work(pwp, NULL);
1762 	}
1763 
1764 	if (work_flags & PMCS_WORK_FLAG_DISCOVER) {
1765 		pmcs_discover(pwp);
1766 	}
1767 
1768 	if (work_flags & PMCS_WORK_FLAG_ABORT_HANDLE) {
1769 		if (pmcs_abort_handler(pwp)) {
1770 			SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
1771 		}
1772 	}
1773 
1774 	if (work_flags & PMCS_WORK_FLAG_SATA_RUN) {
1775 		pmcs_sata_work(pwp);
1776 	}
1777 
1778 	if (work_flags & PMCS_WORK_FLAG_RUN_QUEUES) {
1779 		pmcs_scsa_wq_run(pwp);
1780 		mutex_enter(&pwp->lock);
1781 		PMCS_CQ_RUN(pwp);
1782 		mutex_exit(&pwp->lock);
1783 	}
1784 
1785 	if (work_flags & PMCS_WORK_FLAG_ADD_DMA_CHUNKS) {
1786 		if (pmcs_add_more_chunks(pwp,
1787 		    ptob(1) * PMCS_ADDTL_CHUNK_PAGES)) {
1788 			SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
1789 		} else {
1790 			SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
1791 		}
1792 	}
1793 }
1794 
1795 static int
1796 pmcs_add_more_chunks(pmcs_hw_t *pwp, unsigned long nsize)
1797 {
1798 	pmcs_dmachunk_t *dc;
1799 	unsigned long dl;
1800 	pmcs_chunk_t	*pchunk = NULL;
1801 
1802 	pwp->cip_dma_attr.dma_attr_align = sizeof (uint32_t);
1803 
1804 	pchunk = kmem_zalloc(sizeof (pmcs_chunk_t), KM_SLEEP);
1805 	if (pchunk == NULL) {
1806 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1807 		    "Not enough memory for DMA chunks");
1808 		return (-1);
1809 	}
1810 
1811 	if (pmcs_dma_setup(pwp, &pwp->cip_dma_attr, &pchunk->acc_handle,
1812 	    &pchunk->dma_handle, nsize, (caddr_t *)&pchunk->addrp,
1813 	    &pchunk->dma_addr) == B_FALSE) {
1814 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1815 		    "Failed to setup DMA for chunks");
1816 		kmem_free(pchunk, sizeof (pmcs_chunk_t));
1817 		return (-1);
1818 	}
1819 
1820 	if ((pmcs_check_acc_handle(pchunk->acc_handle) != DDI_SUCCESS) ||
1821 	    (pmcs_check_dma_handle(pchunk->dma_handle) != DDI_SUCCESS)) {
1822 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_UNAFFECTED);
1823 		return (-1);
1824 	}
1825 
1826 	bzero(pchunk->addrp, nsize);
1827 	dc = NULL;
1828 	for (dl = 0; dl < (nsize / PMCS_SGL_CHUNKSZ); dl++) {
1829 		pmcs_dmachunk_t *tmp;
1830 		tmp = kmem_alloc(sizeof (pmcs_dmachunk_t), KM_SLEEP);
1831 		tmp->nxt = dc;
1832 		dc = tmp;
1833 	}
1834 	mutex_enter(&pwp->dma_lock);
1835 	pmcs_idma_chunks(pwp, dc, pchunk, nsize);
1836 	pwp->nchunks++;
1837 	mutex_exit(&pwp->dma_lock);
1838 	return (0);
1839 }
1840 
1841 static void
1842 pmcs_check_forward_progress(pmcs_hw_t *pwp)
1843 {
1844 	uint32_t	cur_iqci;
1845 	uint32_t	cur_msgu_tick;
1846 	uint32_t	cur_iop_tick;
1847 	int 		i;
1848 
1849 	mutex_enter(&pwp->lock);
1850 
1851 	if (pwp->state == STATE_IN_RESET) {
1852 		mutex_exit(&pwp->lock);
1853 		return;
1854 	}
1855 
1856 	/* Ensure that inbound work is getting picked up */
1857 	for (i = 0; i < PMCS_NIQ; i++) {
1858 		cur_iqci = pmcs_rd_iqci(pwp, i);
1859 		if (cur_iqci == pwp->shadow_iqpi[i]) {
1860 			pwp->last_iqci[i] = cur_iqci;
1861 			continue;
1862 		}
1863 		if (cur_iqci == pwp->last_iqci[i]) {
1864 			pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
1865 			    "Inbound Queue stall detected, issuing reset");
1866 			goto hot_reset;
1867 		}
1868 		pwp->last_iqci[i] = cur_iqci;
1869 	}
1870 
1871 	/* Check heartbeat on both the MSGU and IOP */
1872 	cur_msgu_tick = pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK);
1873 	if (cur_msgu_tick == pwp->last_msgu_tick) {
1874 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
1875 		    "Stall detected on MSGU, issuing reset");
1876 		goto hot_reset;
1877 	}
1878 	pwp->last_msgu_tick = cur_msgu_tick;
1879 
1880 	cur_iop_tick  = pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK);
1881 	if (cur_iop_tick == pwp->last_iop_tick) {
1882 		pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
1883 		    "Stall detected on IOP, issuing reset");
1884 		goto hot_reset;
1885 	}
1886 	pwp->last_iop_tick = cur_iop_tick;
1887 
1888 	mutex_exit(&pwp->lock);
1889 	return;
1890 
1891 hot_reset:
1892 	pwp->state = STATE_DEAD;
1893 	/*
1894 	 * We've detected a stall. Attempt to recover service via hot
1895 	 * reset. In case of failure, pmcs_hot_reset() will handle the
1896 	 * failure and issue any required FM notifications.
1897 	 * See pmcs_subr.c for more details.
1898 	 */
1899 	if (pmcs_hot_reset(pwp)) {
1900 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
1901 		    "%s: hot reset failure", __func__);
1902 	} else {
1903 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
1904 		    "%s: hot reset complete", __func__);
1905 		pwp->last_reset_reason = PMCS_LAST_RST_STALL;
1906 	}
1907 	mutex_exit(&pwp->lock);
1908 }
1909 
1910 static void
1911 pmcs_check_commands(pmcs_hw_t *pwp)
1912 {
1913 	pmcs_cmd_t *sp;
1914 	size_t amt;
1915 	char path[32];
1916 	pmcwork_t *pwrk;
1917 	pmcs_xscsi_t *target;
1918 	pmcs_phy_t *phyp;
1919 	int rval;
1920 
1921 	for (pwrk = pwp->work; pwrk < &pwp->work[pwp->max_cmd]; pwrk++) {
1922 		mutex_enter(&pwrk->lock);
1923 
1924 		/*
1925 		 * If the command isn't active, we can't be timing it still.
1926 		 * Active means the tag is not free and the state is "on chip".
1927 		 */
1928 		if (!PMCS_COMMAND_ACTIVE(pwrk)) {
1929 			mutex_exit(&pwrk->lock);
1930 			continue;
1931 		}
1932 
1933 		/*
1934 		 * No timer active for this command.
1935 		 */
1936 		if (pwrk->timer == 0) {
1937 			mutex_exit(&pwrk->lock);
1938 			continue;
1939 		}
1940 
1941 		/*
1942 		 * Knock off bits for the time interval.
1943 		 */
1944 		if (pwrk->timer >= US2WT(PMCS_WATCH_INTERVAL)) {
1945 			pwrk->timer -= US2WT(PMCS_WATCH_INTERVAL);
1946 		} else {
1947 			pwrk->timer = 0;
1948 		}
1949 		if (pwrk->timer > 0) {
1950 			mutex_exit(&pwrk->lock);
1951 			continue;
1952 		}
1953 
1954 		/*
1955 		 * The command has now officially timed out.
1956 		 * Get the path for it. If it doesn't have
1957 		 * a phy pointer any more, it's really dead
1958 		 * and can just be put back on the free list.
1959 		 * There should *not* be any commands associated
1960 		 * with it any more.
1961 		 */
1962 		if (pwrk->phy == NULL) {
1963 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1964 			    "dead command with gone phy being recycled");
1965 			ASSERT(pwrk->xp == NULL);
1966 			pmcs_pwork(pwp, pwrk);
1967 			continue;
1968 		}
1969 		amt = sizeof (path);
1970 		amt = min(sizeof (pwrk->phy->path), amt);
1971 		(void) memcpy(path, pwrk->phy->path, amt);
1972 
1973 		/*
1974 		 * If this is a non-SCSA command, stop here. Eventually
1975 		 * we might do something with non-SCSA commands here-
1976 		 * but so far their timeout mechanisms are handled in
1977 		 * the WAIT_FOR macro.
1978 		 */
1979 		if (pwrk->xp == NULL) {
1980 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1981 			    "%s: non-SCSA cmd tag 0x%x timed out",
1982 			    path, pwrk->htag);
1983 			mutex_exit(&pwrk->lock);
1984 			continue;
1985 		}
1986 
1987 		sp = pwrk->arg;
1988 		ASSERT(sp != NULL);
1989 
1990 		/*
1991 		 * Mark it as timed out.
1992 		 */
1993 		CMD2PKT(sp)->pkt_reason = CMD_TIMEOUT;
1994 		CMD2PKT(sp)->pkt_statistics |= STAT_TIMEOUT;
1995 #ifdef	DEBUG
1996 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pwrk->phy, pwrk->xp,
1997 		    "%s: SCSA cmd tag 0x%x timed out (state %x) onwire=%d",
1998 		    path, pwrk->htag, pwrk->state, pwrk->onwire);
1999 #else
2000 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pwrk->phy, pwrk->xp,
2001 		    "%s: SCSA cmd tag 0x%x timed out (state %x)",
2002 		    path, pwrk->htag, pwrk->state);
2003 #endif
2004 		/*
2005 		 * Mark the work structure as timed out.
2006 		 */
2007 		pwrk->state = PMCS_WORK_STATE_TIMED_OUT;
2008 		phyp = pwrk->phy;
2009 		target = pwrk->xp;
2010 		mutex_exit(&pwrk->lock);
2011 
2012 		pmcs_lock_phy(phyp);
2013 		mutex_enter(&target->statlock);
2014 
2015 		/*
2016 		 * No point attempting recovery if the device is gone
2017 		 */
2018 		if (target->dev_gone) {
2019 			mutex_exit(&target->statlock);
2020 			pmcs_unlock_phy(phyp);
2021 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2022 			    "%s: tgt(0x%p) is gone. Returning CMD_DEV_GONE "
2023 			    "for htag 0x%08x", __func__,
2024 			    (void *)target, pwrk->htag);
2025 			mutex_enter(&pwrk->lock);
2026 			if (!PMCS_COMMAND_DONE(pwrk)) {
2027 				/* Complete this command here */
2028 				pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2029 				    "%s: Completing cmd (htag 0x%08x) "
2030 				    "anyway", __func__, pwrk->htag);
2031 				pwrk->dead = 1;
2032 				CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
2033 				CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
2034 				pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
2035 			} else {
2036 				mutex_exit(&pwrk->lock);
2037 			}
2038 			continue;
2039 		}
2040 
2041 		mutex_exit(&target->statlock);
2042 		rval = pmcs_abort(pwp, phyp, pwrk->htag, 0, 1);
2043 		if (rval) {
2044 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2045 			    "%s: Bad status (%d) on abort of HTAG 0x%08x",
2046 			    __func__, rval, pwrk->htag);
2047 			pmcs_unlock_phy(phyp);
2048 			mutex_enter(&pwrk->lock);
2049 			if (!PMCS_COMMAND_DONE(pwrk)) {
2050 				/* Complete this command here */
2051 				pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
2052 				    "%s: Completing cmd (htag 0x%08x) "
2053 				    "anyway", __func__, pwrk->htag);
2054 				if (target->dev_gone) {
2055 					pwrk->dead = 1;
2056 					CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
2057 					CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
2058 				}
2059 				pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
2060 			} else {
2061 				mutex_exit(&pwrk->lock);
2062 			}
2063 			pmcs_lock_phy(phyp);
2064 			/*
2065 			 * No need to reschedule ABORT if we get any other
2066 			 * status
2067 			 */
2068 			if (rval == ENOMEM) {
2069 				phyp->abort_sent = 0;
2070 				phyp->abort_pending = 1;
2071 				SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
2072 			}
2073 		}
2074 		pmcs_unlock_phy(phyp);
2075 	}
2076 	/*
2077 	 * Run any completions that may have been queued up.
2078 	 */
2079 	PMCS_CQ_RUN(pwp);
2080 }
2081 
2082 static void
2083 pmcs_watchdog(void *arg)
2084 {
2085 	pmcs_hw_t *pwp = arg;
2086 
2087 	DTRACE_PROBE2(pmcs__watchdog, ulong_t, pwp->work_flags, boolean_t,
2088 	    pwp->config_changed);
2089 
2090 	/*
2091 	 * Check forward progress on the chip
2092 	 */
2093 	if (++pwp->watchdog_count == PMCS_FWD_PROG_TRIGGER) {
2094 		pwp->watchdog_count = 0;
2095 		pmcs_check_forward_progress(pwp);
2096 	}
2097 
2098 	/*
2099 	 * Check to see if we need to kick discovery off again
2100 	 */
2101 	mutex_enter(&pwp->config_lock);
2102 	if (pwp->config_restart &&
2103 	    (ddi_get_lbolt() >= pwp->config_restart_time)) {
2104 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2105 		    "%s: Timer expired for re-enumeration: Start discovery",
2106 		    __func__);
2107 		pwp->config_restart = B_FALSE;
2108 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2109 	}
2110 	mutex_exit(&pwp->config_lock);
2111 
2112 	mutex_enter(&pwp->lock);
2113 	if (pwp->state != STATE_RUNNING) {
2114 		mutex_exit(&pwp->lock);
2115 		return;
2116 	}
2117 
2118 	if (atomic_cas_ulong(&pwp->work_flags, 0, 0) != 0) {
2119 		if (ddi_taskq_dispatch(pwp->tq, pmcs_worker, pwp,
2120 		    DDI_NOSLEEP) != DDI_SUCCESS) {
2121 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2122 			    "Could not dispatch to worker thread");
2123 		}
2124 	}
2125 	pwp->wdhandle = timeout(pmcs_watchdog, pwp,
2126 	    drv_usectohz(PMCS_WATCH_INTERVAL));
2127 
2128 	mutex_exit(&pwp->lock);
2129 
2130 	pmcs_check_commands(pwp);
2131 	pmcs_handle_dead_phys(pwp);
2132 }
2133 
2134 static int
2135 pmcs_remove_ihandlers(pmcs_hw_t *pwp, int icnt)
2136 {
2137 	int i, r, rslt = 0;
2138 	for (i = 0; i < icnt; i++) {
2139 		r = ddi_intr_remove_handler(pwp->ih_table[i]);
2140 		if (r == DDI_SUCCESS) {
2141 			continue;
2142 		}
2143 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2144 		    "%s: unable to remove interrupt handler %d", __func__, i);
2145 		rslt = -1;
2146 		break;
2147 	}
2148 	return (rslt);
2149 }
2150 
2151 static int
2152 pmcs_disable_intrs(pmcs_hw_t *pwp, int icnt)
2153 {
2154 	if (pwp->intr_cap & DDI_INTR_FLAG_BLOCK) {
2155 		int r = ddi_intr_block_disable(&pwp->ih_table[0],
2156 		    pwp->intr_cnt);
2157 		if (r != DDI_SUCCESS) {
2158 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2159 			    "unable to disable interrupt block");
2160 			return (-1);
2161 		}
2162 	} else {
2163 		int i;
2164 		for (i = 0; i < icnt; i++) {
2165 			if (ddi_intr_disable(pwp->ih_table[i]) == DDI_SUCCESS) {
2166 				continue;
2167 			}
2168 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2169 			    "unable to disable interrupt %d", i);
2170 			return (-1);
2171 		}
2172 	}
2173 	return (0);
2174 }
2175 
2176 static int
2177 pmcs_free_intrs(pmcs_hw_t *pwp, int icnt)
2178 {
2179 	int i;
2180 	for (i = 0; i < icnt; i++) {
2181 		if (ddi_intr_free(pwp->ih_table[i]) == DDI_SUCCESS) {
2182 			continue;
2183 		}
2184 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2185 		    "unable to free interrupt %d", i);
2186 		return (-1);
2187 	}
2188 	kmem_free(pwp->ih_table, pwp->ih_table_size);
2189 	pwp->ih_table_size = 0;
2190 	return (0);
2191 }
2192 
2193 /*
2194  * Try to set up interrupts of type "type" with a minimum number of interrupts
2195  * of "min".
2196  */
2197 static void
2198 pmcs_setup_intr_impl(pmcs_hw_t *pwp, int type, int min)
2199 {
2200 	int rval, avail, count, actual, max;
2201 
2202 	rval = ddi_intr_get_nintrs(pwp->dip, type, &count);
2203 	if ((rval != DDI_SUCCESS) || (count < min)) {
2204 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2205 		    "%s: get_nintrs failed; type: %d rc: %d count: %d min: %d",
2206 		    __func__, type, rval, count, min);
2207 		return;
2208 	}
2209 
2210 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2211 	    "%s: nintrs = %d for type: %d", __func__, count, type);
2212 
2213 	rval = ddi_intr_get_navail(pwp->dip, type, &avail);
2214 	if ((rval != DDI_SUCCESS) || (avail < min)) {
2215 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2216 		    "%s: get_navail failed; type: %d rc: %d avail: %d min: %d",
2217 		    __func__, type, rval, avail, min);
2218 		return;
2219 	}
2220 
2221 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2222 	    "%s: navail = %d for type: %d", __func__, avail, type);
2223 
2224 	pwp->ih_table_size = avail * sizeof (ddi_intr_handle_t);
2225 	pwp->ih_table = kmem_alloc(pwp->ih_table_size, KM_SLEEP);
2226 
2227 	switch (type) {
2228 	case DDI_INTR_TYPE_MSIX:
2229 		pwp->int_type = PMCS_INT_MSIX;
2230 		max = PMCS_MAX_MSIX;
2231 		break;
2232 	case DDI_INTR_TYPE_MSI:
2233 		pwp->int_type = PMCS_INT_MSI;
2234 		max = PMCS_MAX_MSI;
2235 		break;
2236 	case DDI_INTR_TYPE_FIXED:
2237 	default:
2238 		pwp->int_type = PMCS_INT_FIXED;
2239 		max = PMCS_MAX_FIXED;
2240 		break;
2241 	}
2242 
2243 	rval = ddi_intr_alloc(pwp->dip, pwp->ih_table, type, 0, max, &actual,
2244 	    DDI_INTR_ALLOC_NORMAL);
2245 	if (rval != DDI_SUCCESS) {
2246 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2247 		    "%s: ddi_intr_alloc failed; type: %d rc: %d",
2248 		    __func__, type, rval);
2249 		kmem_free(pwp->ih_table, pwp->ih_table_size);
2250 		pwp->ih_table = NULL;
2251 		pwp->ih_table_size = 0;
2252 		pwp->intr_cnt = 0;
2253 		pwp->int_type = PMCS_INT_NONE;
2254 		return;
2255 	}
2256 
2257 	pwp->intr_cnt = actual;
2258 }
2259 
2260 /*
2261  * Set up interrupts.
2262  * We return one of three values:
2263  *
2264  * 0 - success
2265  * EAGAIN - failure to set up interrupts
2266  * EIO - "" + we're now stuck partly enabled
2267  *
2268  * If EIO is returned, we can't unload the driver.
2269  */
2270 static int
2271 pmcs_setup_intr(pmcs_hw_t *pwp)
2272 {
2273 	int i, r, itypes, oqv_count;
2274 	ddi_intr_handler_t **iv_table;
2275 	size_t iv_table_size;
2276 	uint_t pri;
2277 
2278 	if (ddi_intr_get_supported_types(pwp->dip, &itypes) != DDI_SUCCESS) {
2279 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2280 		    "cannot get interrupt types");
2281 		return (EAGAIN);
2282 	}
2283 
2284 	if (disable_msix) {
2285 		itypes &= ~DDI_INTR_TYPE_MSIX;
2286 	}
2287 	if (disable_msi) {
2288 		itypes &= ~DDI_INTR_TYPE_MSI;
2289 	}
2290 
2291 	/*
2292 	 * We won't know what firmware we're running until we call pmcs_setup,
2293 	 * and we can't call pmcs_setup until we establish interrupts.
2294 	 */
2295 
2296 	pwp->int_type = PMCS_INT_NONE;
2297 
2298 	/*
2299 	 * We want PMCS_MAX_MSIX vectors for MSI-X.  Anything less would be
2300 	 * uncivilized.
2301 	 */
2302 	if (itypes & DDI_INTR_TYPE_MSIX) {
2303 		pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_MSIX, PMCS_MAX_MSIX);
2304 		if (pwp->int_type == PMCS_INT_MSIX) {
2305 			itypes = 0;
2306 		}
2307 	}
2308 
2309 	if (itypes & DDI_INTR_TYPE_MSI) {
2310 		pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_MSI, 1);
2311 		if (pwp->int_type == PMCS_INT_MSI) {
2312 			itypes = 0;
2313 		}
2314 	}
2315 
2316 	if (itypes & DDI_INTR_TYPE_FIXED) {
2317 		pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_FIXED, 1);
2318 		if (pwp->int_type == PMCS_INT_FIXED) {
2319 			itypes = 0;
2320 		}
2321 	}
2322 
2323 	if (pwp->intr_cnt == 0) {
2324 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
2325 		    "No interrupts available");
2326 		return (EAGAIN);
2327 	}
2328 
2329 	iv_table_size = sizeof (ddi_intr_handler_t *) * pwp->intr_cnt;
2330 	iv_table = kmem_alloc(iv_table_size, KM_SLEEP);
2331 
2332 	/*
2333 	 * Get iblock cookie and add handlers.
2334 	 */
2335 	switch (pwp->intr_cnt) {
2336 	case 1:
2337 		iv_table[0] = pmcs_all_intr;
2338 		break;
2339 	case 2:
2340 		iv_table[0] = pmcs_iodone_ix;
2341 		iv_table[1] = pmcs_nonio_ix;
2342 		break;
2343 	case 4:
2344 		iv_table[PMCS_MSIX_GENERAL] = pmcs_general_ix;
2345 		iv_table[PMCS_MSIX_IODONE] = pmcs_iodone_ix;
2346 		iv_table[PMCS_MSIX_EVENTS] = pmcs_event_ix;
2347 		iv_table[PMCS_MSIX_FATAL] = pmcs_fatal_ix;
2348 		break;
2349 	default:
2350 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2351 		    "%s: intr_cnt = %d - unexpected", __func__, pwp->intr_cnt);
2352 		kmem_free(iv_table, iv_table_size);
2353 		return (EAGAIN);
2354 	}
2355 
2356 	for (i = 0; i < pwp->intr_cnt; i++) {
2357 		r = ddi_intr_add_handler(pwp->ih_table[i], iv_table[i],
2358 		    (caddr_t)pwp, NULL);
2359 		if (r != DDI_SUCCESS) {
2360 			kmem_free(iv_table, iv_table_size);
2361 			if (pmcs_remove_ihandlers(pwp, i)) {
2362 				return (EIO);
2363 			}
2364 			if (pmcs_free_intrs(pwp, i)) {
2365 				return (EIO);
2366 			}
2367 			pwp->intr_cnt = 0;
2368 			return (EAGAIN);
2369 		}
2370 	}
2371 
2372 	kmem_free(iv_table, iv_table_size);
2373 
2374 	if (ddi_intr_get_cap(pwp->ih_table[0], &pwp->intr_cap) != DDI_SUCCESS) {
2375 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2376 		    "unable to get int capabilities");
2377 		if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2378 			return (EIO);
2379 		}
2380 		if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2381 			return (EIO);
2382 		}
2383 		pwp->intr_cnt = 0;
2384 		return (EAGAIN);
2385 	}
2386 
2387 	if (pwp->intr_cap & DDI_INTR_FLAG_BLOCK) {
2388 		r = ddi_intr_block_enable(&pwp->ih_table[0], pwp->intr_cnt);
2389 		if (r != DDI_SUCCESS) {
2390 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2391 			    "intr blk enable failed");
2392 			if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2393 				return (EIO);
2394 			}
2395 			if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2396 				return (EIO);
2397 			}
2398 			pwp->intr_cnt = 0;
2399 			return (EFAULT);
2400 		}
2401 	} else {
2402 		for (i = 0; i < pwp->intr_cnt; i++) {
2403 			r = ddi_intr_enable(pwp->ih_table[i]);
2404 			if (r == DDI_SUCCESS) {
2405 				continue;
2406 			}
2407 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2408 			    "unable to enable interrupt %d", i);
2409 			if (pmcs_disable_intrs(pwp, i)) {
2410 				return (EIO);
2411 			}
2412 			if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2413 				return (EIO);
2414 			}
2415 			if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2416 				return (EIO);
2417 			}
2418 			pwp->intr_cnt = 0;
2419 			return (EAGAIN);
2420 		}
2421 	}
2422 
2423 	/*
2424 	 * Set up locks.
2425 	 */
2426 	if (ddi_intr_get_pri(pwp->ih_table[0], &pri) != DDI_SUCCESS) {
2427 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2428 		    "unable to get interrupt priority");
2429 		if (pmcs_disable_intrs(pwp, pwp->intr_cnt)) {
2430 			return (EIO);
2431 		}
2432 		if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2433 			return (EIO);
2434 		}
2435 		if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2436 			return (EIO);
2437 		}
2438 		pwp->intr_cnt = 0;
2439 		return (EAGAIN);
2440 	}
2441 
2442 	pwp->locks_initted = 1;
2443 	pwp->intr_pri = pri;
2444 	mutex_init(&pwp->lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2445 	mutex_init(&pwp->dma_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2446 	mutex_init(&pwp->axil_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2447 	mutex_init(&pwp->cq_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2448 	mutex_init(&pwp->ict_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2449 	mutex_init(&pwp->config_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2450 	mutex_init(&pwp->wfree_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2451 	mutex_init(&pwp->pfree_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2452 	mutex_init(&pwp->dead_phylist_lock, NULL, MUTEX_DRIVER,
2453 	    DDI_INTR_PRI(pri));
2454 #ifdef	DEBUG
2455 	mutex_init(&pwp->dbglock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
2456 #endif
2457 	cv_init(&pwp->ict_cv, NULL, CV_DRIVER, NULL);
2458 	cv_init(&pwp->drain_cv, NULL, CV_DRIVER, NULL);
2459 	for (i = 0; i < PMCS_NIQ; i++) {
2460 		mutex_init(&pwp->iqp_lock[i], NULL,
2461 		    MUTEX_DRIVER, DDI_INTR_PRI(pwp->intr_pri));
2462 	}
2463 	for (i = 0; i < pwp->cq_info.cq_threads; i++) {
2464 		mutex_init(&pwp->cq_info.cq_thr_info[i].cq_thr_lock, NULL,
2465 		    MUTEX_DRIVER, DDI_INTR_PRI(pwp->intr_pri));
2466 		cv_init(&pwp->cq_info.cq_thr_info[i].cq_cv, NULL,
2467 		    CV_DRIVER, NULL);
2468 	}
2469 
2470 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "%d %s interrup%s configured",
2471 	    pwp->intr_cnt, (pwp->int_type == PMCS_INT_MSIX)? "MSI-X" :
2472 	    ((pwp->int_type == PMCS_INT_MSI)? "MSI" : "INT-X"),
2473 	    pwp->intr_cnt == 1? "t" : "ts");
2474 
2475 
2476 	/*
2477 	 * Enable Interrupts
2478 	 */
2479 	if (pwp->intr_cnt > PMCS_NOQ) {
2480 		oqv_count = pwp->intr_cnt;
2481 	} else {
2482 		oqv_count = PMCS_NOQ;
2483 	}
2484 	for (pri = 0xffffffff, i = 0; i < oqv_count; i++) {
2485 		pri ^= (1 << i);
2486 	}
2487 
2488 	mutex_enter(&pwp->lock);
2489 	pwp->intr_mask = pri;
2490 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, pwp->intr_mask);
2491 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
2492 	mutex_exit(&pwp->lock);
2493 
2494 	return (0);
2495 }
2496 
2497 static int
2498 pmcs_teardown_intr(pmcs_hw_t *pwp)
2499 {
2500 	if (pwp->intr_cnt) {
2501 		if (pmcs_disable_intrs(pwp, pwp->intr_cnt)) {
2502 			return (EIO);
2503 		}
2504 		if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
2505 			return (EIO);
2506 		}
2507 		if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
2508 			return (EIO);
2509 		}
2510 		pwp->intr_cnt = 0;
2511 	}
2512 	return (0);
2513 }
2514 
2515 static uint_t
2516 pmcs_general_ix(caddr_t arg1, caddr_t arg2)
2517 {
2518 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2519 	_NOTE(ARGUNUSED(arg2));
2520 	pmcs_general_intr(pwp);
2521 	return (DDI_INTR_CLAIMED);
2522 }
2523 
2524 static uint_t
2525 pmcs_event_ix(caddr_t arg1, caddr_t arg2)
2526 {
2527 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2528 	_NOTE(ARGUNUSED(arg2));
2529 	pmcs_event_intr(pwp);
2530 	return (DDI_INTR_CLAIMED);
2531 }
2532 
2533 static uint_t
2534 pmcs_iodone_ix(caddr_t arg1, caddr_t arg2)
2535 {
2536 	_NOTE(ARGUNUSED(arg2));
2537 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2538 
2539 	/*
2540 	 * It's possible that if we just turned interrupt coalescing off
2541 	 * (and thus, re-enabled auto clear for interrupts on the I/O outbound
2542 	 * queue) that there was an interrupt already pending.  We use
2543 	 * io_intr_coal.int_cleared to ensure that we still drop in here and
2544 	 * clear the appropriate interrupt bit one last time.
2545 	 */
2546 	mutex_enter(&pwp->ict_lock);
2547 	if (pwp->io_intr_coal.timer_on ||
2548 	    (pwp->io_intr_coal.int_cleared == B_FALSE)) {
2549 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2550 		    (1 << PMCS_OQ_IODONE));
2551 		pwp->io_intr_coal.int_cleared = B_TRUE;
2552 	}
2553 	mutex_exit(&pwp->ict_lock);
2554 
2555 	pmcs_iodone_intr(pwp);
2556 
2557 	return (DDI_INTR_CLAIMED);
2558 }
2559 
2560 static uint_t
2561 pmcs_fatal_ix(caddr_t arg1, caddr_t arg2)
2562 {
2563 	pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
2564 	_NOTE(ARGUNUSED(arg2));
2565 	pmcs_fatal_handler(pwp);
2566 	return (DDI_INTR_CLAIMED);
2567 }
2568 
2569 static uint_t
2570 pmcs_nonio_ix(caddr_t arg1, caddr_t arg2)
2571 {
2572 	_NOTE(ARGUNUSED(arg2));
2573 	pmcs_hw_t *pwp = (void *)arg1;
2574 	uint32_t obdb = pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB);
2575 
2576 	/*
2577 	 * Check for Fatal Interrupts
2578 	 */
2579 	if (obdb & (1 << PMCS_FATAL_INTERRUPT)) {
2580 		pmcs_fatal_handler(pwp);
2581 		return (DDI_INTR_CLAIMED);
2582 	}
2583 
2584 	if (obdb & (1 << PMCS_OQ_GENERAL)) {
2585 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2586 		    (1 << PMCS_OQ_GENERAL));
2587 		pmcs_general_intr(pwp);
2588 		pmcs_event_intr(pwp);
2589 	}
2590 
2591 	return (DDI_INTR_CLAIMED);
2592 }
2593 
2594 static uint_t
2595 pmcs_all_intr(caddr_t arg1, caddr_t arg2)
2596 {
2597 	_NOTE(ARGUNUSED(arg2));
2598 	pmcs_hw_t *pwp = (void *) arg1;
2599 	uint32_t obdb;
2600 	int handled = 0;
2601 
2602 	obdb = pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB);
2603 
2604 	/*
2605 	 * Check for Fatal Interrupts
2606 	 */
2607 	if (obdb & (1 << PMCS_FATAL_INTERRUPT)) {
2608 		pmcs_fatal_handler(pwp);
2609 		return (DDI_INTR_CLAIMED);
2610 	}
2611 
2612 	/*
2613 	 * Check for Outbound Queue service needed
2614 	 */
2615 	if (obdb & (1 << PMCS_OQ_IODONE)) {
2616 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2617 		    (1 << PMCS_OQ_IODONE));
2618 		obdb ^= (1 << PMCS_OQ_IODONE);
2619 		handled++;
2620 		pmcs_iodone_intr(pwp);
2621 	}
2622 	if (obdb & (1 << PMCS_OQ_GENERAL)) {
2623 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2624 		    (1 << PMCS_OQ_GENERAL));
2625 		obdb ^= (1 << PMCS_OQ_GENERAL);
2626 		handled++;
2627 		pmcs_general_intr(pwp);
2628 	}
2629 	if (obdb & (1 << PMCS_OQ_EVENTS)) {
2630 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
2631 		    (1 << PMCS_OQ_EVENTS));
2632 		obdb ^= (1 << PMCS_OQ_EVENTS);
2633 		handled++;
2634 		pmcs_event_intr(pwp);
2635 	}
2636 	if (obdb) {
2637 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
2638 		    "interrupt bits not handled (0x%x)", obdb);
2639 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, obdb);
2640 		handled++;
2641 	}
2642 	if (pwp->int_type == PMCS_INT_MSI) {
2643 		handled++;
2644 	}
2645 	return (handled? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED);
2646 }
2647 
2648 void
2649 pmcs_fatal_handler(pmcs_hw_t *pwp)
2650 {
2651 	pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, "Fatal Interrupt caught");
2652 
2653 	mutex_enter(&pwp->lock);
2654 	pwp->state = STATE_DEAD;
2655 
2656 	/*
2657 	 * Attempt a hot reset. In case of failure, pmcs_hot_reset() will
2658 	 * handle the failure and issue any required FM notifications.
2659 	 * See pmcs_subr.c for more details.
2660 	 */
2661 	if (pmcs_hot_reset(pwp)) {
2662 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
2663 		    "%s: hot reset failure", __func__);
2664 	} else {
2665 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
2666 		    "%s: hot reset complete", __func__);
2667 		pwp->last_reset_reason = PMCS_LAST_RST_FATAL_ERROR;
2668 	}
2669 	mutex_exit(&pwp->lock);
2670 }
2671 
2672 /*
2673  * Called with PHY lock and target statlock held and scratch acquired.
2674  */
2675 boolean_t
2676 pmcs_assign_device(pmcs_hw_t *pwp, pmcs_xscsi_t *tgt)
2677 {
2678 	pmcs_phy_t *pptr = tgt->phy;
2679 
2680 	switch (pptr->dtype) {
2681 	case SAS:
2682 	case EXPANDER:
2683 		break;
2684 	case SATA:
2685 		tgt->ca = 1;
2686 		break;
2687 	default:
2688 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
2689 		    "%s: Target %p has PHY %p with invalid dtype",
2690 		    __func__, (void *)tgt, (void *)pptr);
2691 		return (B_FALSE);
2692 	}
2693 
2694 	tgt->new = 1;
2695 	tgt->dev_gone = 0;
2696 	tgt->recover_wait = 0;
2697 
2698 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
2699 	    "%s: config %s vtgt %u for " SAS_ADDR_FMT, __func__,
2700 	    pptr->path, tgt->target_num, SAS_ADDR_PRT(pptr->sas_address));
2701 
2702 	if (pmcs_add_new_device(pwp, tgt) != B_TRUE) {
2703 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
2704 		    "%s: Failed for vtgt %u / WWN " SAS_ADDR_FMT, __func__,
2705 		    tgt->target_num, SAS_ADDR_PRT(pptr->sas_address));
2706 		mutex_destroy(&tgt->statlock);
2707 		mutex_destroy(&tgt->wqlock);
2708 		mutex_destroy(&tgt->aqlock);
2709 		return (B_FALSE);
2710 	}
2711 
2712 	return (B_TRUE);
2713 }
2714 
2715 /*
2716  * Called with softstate lock held
2717  */
2718 void
2719 pmcs_remove_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2720 {
2721 	pmcs_xscsi_t *xp;
2722 	unsigned int vtgt;
2723 
2724 	ASSERT(mutex_owned(&pwp->lock));
2725 
2726 	for (vtgt = 0; vtgt < pwp->max_dev; vtgt++) {
2727 		xp = pwp->targets[vtgt];
2728 		if (xp == NULL) {
2729 			continue;
2730 		}
2731 
2732 		mutex_enter(&xp->statlock);
2733 		if (xp->phy == pptr) {
2734 			if (xp->new) {
2735 				xp->new = 0;
2736 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
2737 				    "cancel config of vtgt %u", vtgt);
2738 			} else {
2739 				pmcs_clear_xp(pwp, xp);
2740 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
2741 				    "Removed tgt 0x%p vtgt %u",
2742 				    (void *)xp, vtgt);
2743 			}
2744 			mutex_exit(&xp->statlock);
2745 			break;
2746 		}
2747 		mutex_exit(&xp->statlock);
2748 	}
2749 }
2750 
2751 void
2752 pmcs_prt_impl(pmcs_hw_t *pwp, pmcs_prt_level_t level,
2753     pmcs_phy_t *phyp, pmcs_xscsi_t *target, const char *fmt, ...)
2754 {
2755 	va_list	ap;
2756 	int written = 0;
2757 	char *ptr;
2758 	uint32_t elem_size = PMCS_TBUF_ELEM_SIZE - 1;
2759 	boolean_t system_log;
2760 	int system_log_level;
2761 
2762 	switch (level) {
2763 	case PMCS_PRT_DEBUG_DEVEL:
2764 	case PMCS_PRT_DEBUG_DEV_STATE:
2765 	case PMCS_PRT_DEBUG_PHY_LOCKING:
2766 	case PMCS_PRT_DEBUG_SCSI_STATUS:
2767 	case PMCS_PRT_DEBUG_UNDERFLOW:
2768 	case PMCS_PRT_DEBUG_CONFIG:
2769 	case PMCS_PRT_DEBUG_IPORT:
2770 	case PMCS_PRT_DEBUG_MAP:
2771 	case PMCS_PRT_DEBUG3:
2772 	case PMCS_PRT_DEBUG2:
2773 	case PMCS_PRT_DEBUG1:
2774 	case PMCS_PRT_DEBUG:
2775 		system_log = B_FALSE;
2776 		break;
2777 	case PMCS_PRT_INFO:
2778 		system_log = B_TRUE;
2779 		system_log_level = CE_CONT;
2780 		break;
2781 	case PMCS_PRT_WARN:
2782 		system_log = B_TRUE;
2783 		system_log_level = CE_NOTE;
2784 		break;
2785 	case PMCS_PRT_ERR:
2786 		system_log = B_TRUE;
2787 		system_log_level = CE_WARN;
2788 		break;
2789 	default:
2790 		return;
2791 	}
2792 
2793 	mutex_enter(&pmcs_trace_lock);
2794 	gethrestime(&pmcs_tbuf_ptr->timestamp);
2795 	ptr = pmcs_tbuf_ptr->buf;
2796 
2797 	/*
2798 	 * Store the pertinent PHY and target information if there is any
2799 	 */
2800 	if (target == NULL) {
2801 		pmcs_tbuf_ptr->target_num = PMCS_INVALID_TARGET_NUM;
2802 		pmcs_tbuf_ptr->target_ua[0] = '\0';
2803 	} else {
2804 		pmcs_tbuf_ptr->target_num = target->target_num;
2805 		(void) strncpy(pmcs_tbuf_ptr->target_ua, target->ua,
2806 		    PMCS_TBUF_UA_MAX_SIZE);
2807 	}
2808 
2809 	if (phyp == NULL) {
2810 		(void) memset(pmcs_tbuf_ptr->phy_sas_address, 0, 8);
2811 		pmcs_tbuf_ptr->phy_path[0] = '\0';
2812 		pmcs_tbuf_ptr->phy_dtype = NOTHING;
2813 	} else {
2814 		(void) memcpy(pmcs_tbuf_ptr->phy_sas_address,
2815 		    phyp->sas_address, 8);
2816 		(void) strncpy(pmcs_tbuf_ptr->phy_path, phyp->path, 32);
2817 		pmcs_tbuf_ptr->phy_dtype = phyp->dtype;
2818 	}
2819 
2820 	written += snprintf(ptr, elem_size, "pmcs%d:%d: ",
2821 	    ddi_get_instance(pwp->dip), level);
2822 	ptr += strlen(ptr);
2823 	va_start(ap, fmt);
2824 	written += vsnprintf(ptr, elem_size - written, fmt, ap);
2825 	va_end(ap);
2826 	if (written > elem_size - 1) {
2827 		/* Indicate truncation */
2828 		pmcs_tbuf_ptr->buf[elem_size - 1] = '+';
2829 	}
2830 	if (++pmcs_tbuf_idx == pmcs_tbuf_num_elems) {
2831 		pmcs_tbuf_ptr = pmcs_tbuf;
2832 		pmcs_tbuf_wrap = B_TRUE;
2833 		pmcs_tbuf_idx = 0;
2834 	} else {
2835 		++pmcs_tbuf_ptr;
2836 	}
2837 	mutex_exit(&pmcs_trace_lock);
2838 
2839 	/*
2840 	 * When pmcs_force_syslog in non-zero, everything goes also
2841 	 * to syslog, at CE_CONT level.
2842 	 */
2843 	if (pmcs_force_syslog) {
2844 		system_log = B_TRUE;
2845 		system_log_level = CE_CONT;
2846 	}
2847 
2848 	/*
2849 	 * Anything that comes in with PMCS_PRT_INFO, WARN, or ERR also
2850 	 * goes to syslog.
2851 	 */
2852 	if (system_log) {
2853 		char local[196];
2854 
2855 		switch (system_log_level) {
2856 		case CE_CONT:
2857 			(void) snprintf(local, sizeof (local), "%sINFO: ",
2858 			    pmcs_console ? "" : "?");
2859 			break;
2860 		case CE_NOTE:
2861 		case CE_WARN:
2862 			local[0] = 0;
2863 			break;
2864 		default:
2865 			return;
2866 		}
2867 
2868 		ptr = local;
2869 		ptr += strlen(local);
2870 		(void) snprintf(ptr, (sizeof (local)) -
2871 		    ((size_t)ptr - (size_t)local), "pmcs%d: ",
2872 		    ddi_get_instance(pwp->dip));
2873 		ptr += strlen(ptr);
2874 		va_start(ap, fmt);
2875 		(void) vsnprintf(ptr,
2876 		    (sizeof (local)) - ((size_t)ptr - (size_t)local), fmt, ap);
2877 		va_end(ap);
2878 		if (level == CE_CONT) {
2879 			(void) strlcat(local, "\n", sizeof (local));
2880 		}
2881 		cmn_err(system_log_level, local);
2882 	}
2883 
2884 }
2885 
2886 /*
2887  * pmcs_acquire_scratch
2888  *
2889  * If "wait" is true, the caller will wait until it can acquire the scratch.
2890  * This implies the caller needs to be in a context where spinning for an
2891  * indeterminate amount of time is acceptable.
2892  */
2893 int
2894 pmcs_acquire_scratch(pmcs_hw_t *pwp, boolean_t wait)
2895 {
2896 	int rval;
2897 
2898 	if (!wait) {
2899 		return (atomic_swap_8(&pwp->scratch_locked, 1));
2900 	}
2901 
2902 	/*
2903 	 * Caller will wait for scratch.
2904 	 */
2905 	while ((rval = atomic_swap_8(&pwp->scratch_locked, 1)) != 0) {
2906 		drv_usecwait(100);
2907 	}
2908 
2909 	return (rval);
2910 }
2911 
2912 void
2913 pmcs_release_scratch(pmcs_hw_t *pwp)
2914 {
2915 	pwp->scratch_locked = 0;
2916 }
2917 
2918 static void
2919 pmcs_create_phy_stats(pmcs_iport_t *iport)
2920 {
2921 	sas_phy_stats_t		*ps;
2922 	pmcs_hw_t		*pwp;
2923 	pmcs_phy_t		*phyp;
2924 	int			ndata;
2925 	char			ks_name[KSTAT_STRLEN];
2926 
2927 	ASSERT(iport != NULL);
2928 	pwp = iport->pwp;
2929 	ASSERT(pwp != NULL);
2930 
2931 	mutex_enter(&iport->lock);
2932 
2933 	for (phyp = list_head(&iport->phys);
2934 	    phyp != NULL;
2935 	    phyp = list_next(&iport->phys, phyp)) {
2936 
2937 		pmcs_lock_phy(phyp);
2938 
2939 		if (phyp->phy_stats != NULL) {
2940 			pmcs_unlock_phy(phyp);
2941 			/* We've already created this kstat instance */
2942 			continue;
2943 		}
2944 
2945 		ndata = (sizeof (sas_phy_stats_t)/sizeof (kstat_named_t));
2946 
2947 		(void) snprintf(ks_name, sizeof (ks_name),
2948 		    "%s.%llx.%d.%d", ddi_driver_name(iport->dip),
2949 		    (longlong_t)pwp->sas_wwns[0],
2950 		    ddi_get_instance(iport->dip), phyp->phynum);
2951 
2952 		phyp->phy_stats = kstat_create("pmcs",
2953 		    ddi_get_instance(iport->dip), ks_name, KSTAT_SAS_PHY_CLASS,
2954 		    KSTAT_TYPE_NAMED, ndata, 0);
2955 
2956 		if (phyp->phy_stats == NULL) {
2957 			pmcs_unlock_phy(phyp);
2958 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL,
2959 			    "%s: Failed to create %s kstats", __func__,
2960 			    ks_name);
2961 			continue;
2962 		}
2963 
2964 		ps = (sas_phy_stats_t *)phyp->phy_stats->ks_data;
2965 
2966 		kstat_named_init(&ps->seconds_since_last_reset,
2967 		    "SecondsSinceLastReset", KSTAT_DATA_ULONGLONG);
2968 		kstat_named_init(&ps->tx_frames,
2969 		    "TxFrames", KSTAT_DATA_ULONGLONG);
2970 		kstat_named_init(&ps->rx_frames,
2971 		    "RxFrames", KSTAT_DATA_ULONGLONG);
2972 		kstat_named_init(&ps->tx_words,
2973 		    "TxWords", KSTAT_DATA_ULONGLONG);
2974 		kstat_named_init(&ps->rx_words,
2975 		    "RxWords", KSTAT_DATA_ULONGLONG);
2976 		kstat_named_init(&ps->invalid_dword_count,
2977 		    "InvalidDwordCount", KSTAT_DATA_ULONGLONG);
2978 		kstat_named_init(&ps->running_disparity_error_count,
2979 		    "RunningDisparityErrorCount", KSTAT_DATA_ULONGLONG);
2980 		kstat_named_init(&ps->loss_of_dword_sync_count,
2981 		    "LossofDwordSyncCount", KSTAT_DATA_ULONGLONG);
2982 		kstat_named_init(&ps->phy_reset_problem_count,
2983 		    "PhyResetProblemCount", KSTAT_DATA_ULONGLONG);
2984 
2985 		phyp->phy_stats->ks_private = phyp;
2986 		phyp->phy_stats->ks_update = pmcs_update_phy_stats;
2987 		kstat_install(phyp->phy_stats);
2988 		pmcs_unlock_phy(phyp);
2989 	}
2990 
2991 	mutex_exit(&iport->lock);
2992 }
2993 
2994 int
2995 pmcs_update_phy_stats(kstat_t *ks, int rw)
2996 {
2997 	int		val, ret = DDI_FAILURE;
2998 	pmcs_phy_t	*pptr = (pmcs_phy_t *)ks->ks_private;
2999 	pmcs_hw_t	*pwp = pptr->pwp;
3000 	sas_phy_stats_t	*ps = ks->ks_data;
3001 
3002 	_NOTE(ARGUNUSED(rw));
3003 	ASSERT((pptr != NULL) && (pwp != NULL));
3004 
3005 	/*
3006 	 * We just want to lock against other invocations of kstat;
3007 	 * we don't need to pmcs_lock_phy() for this.
3008 	 */
3009 	mutex_enter(&pptr->phy_lock);
3010 
3011 	/* Get Stats from Chip */
3012 	val = pmcs_get_diag_report(pwp, PMCS_INVALID_DWORD_CNT, pptr->phynum);
3013 	if (val == DDI_FAILURE)
3014 		goto fail;
3015 	ps->invalid_dword_count.value.ull = (unsigned long long)val;
3016 
3017 	val = pmcs_get_diag_report(pwp, PMCS_DISPARITY_ERR_CNT, pptr->phynum);
3018 	if (val == DDI_FAILURE)
3019 		goto fail;
3020 	ps->running_disparity_error_count.value.ull = (unsigned long long)val;
3021 
3022 	val = pmcs_get_diag_report(pwp, PMCS_LOST_DWORD_SYNC_CNT, pptr->phynum);
3023 	if (val == DDI_FAILURE)
3024 		goto fail;
3025 	ps->loss_of_dword_sync_count.value.ull = (unsigned long long)val;
3026 
3027 	val = pmcs_get_diag_report(pwp, PMCS_RESET_FAILED_CNT, pptr->phynum);
3028 	if (val == DDI_FAILURE)
3029 		goto fail;
3030 	ps->phy_reset_problem_count.value.ull = (unsigned long long)val;
3031 
3032 	ret = DDI_SUCCESS;
3033 fail:
3034 	mutex_exit(&pptr->phy_lock);
3035 	return (ret);
3036 }
3037 
3038 static void
3039 pmcs_destroy_phy_stats(pmcs_iport_t *iport)
3040 {
3041 	pmcs_phy_t		*phyp;
3042 
3043 	ASSERT(iport != NULL);
3044 	mutex_enter(&iport->lock);
3045 	phyp = iport->pptr;
3046 	if (phyp == NULL) {
3047 		mutex_exit(&iport->lock);
3048 		return;
3049 	}
3050 
3051 	pmcs_lock_phy(phyp);
3052 	if (phyp->phy_stats != NULL) {
3053 		kstat_delete(phyp->phy_stats);
3054 		phyp->phy_stats = NULL;
3055 	}
3056 	pmcs_unlock_phy(phyp);
3057 
3058 	mutex_exit(&iport->lock);
3059 }
3060 
3061 /*ARGSUSED*/
3062 static int
3063 pmcs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
3064 {
3065 	/*
3066 	 * as the driver can always deal with an error in any dma or
3067 	 * access handle, we can just return the fme_status value.
3068 	 */
3069 	pci_ereport_post(dip, err, NULL);
3070 	return (err->fme_status);
3071 }
3072 
3073 static void
3074 pmcs_fm_init(pmcs_hw_t *pwp)
3075 {
3076 	ddi_iblock_cookie_t	fm_ibc;
3077 
3078 	/* Only register with IO Fault Services if we have some capability */
3079 	if (pwp->fm_capabilities) {
3080 		/* Adjust access and dma attributes for FMA */
3081 		pwp->reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
3082 		pwp->iqp_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3083 		pwp->oqp_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3084 		pwp->cip_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3085 		pwp->fwlog_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
3086 
3087 		/*
3088 		 * Register capabilities with IO Fault Services.
3089 		 */
3090 		ddi_fm_init(pwp->dip, &pwp->fm_capabilities, &fm_ibc);
3091 
3092 		/*
3093 		 * Initialize pci ereport capabilities if ereport
3094 		 * capable (should always be.)
3095 		 */
3096 		if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities) ||
3097 		    DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3098 			pci_ereport_setup(pwp->dip);
3099 		}
3100 
3101 		/*
3102 		 * Register error callback if error callback capable.
3103 		 */
3104 		if (DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3105 			ddi_fm_handler_register(pwp->dip,
3106 			    pmcs_fm_error_cb, (void *) pwp);
3107 		}
3108 	}
3109 }
3110 
3111 static void
3112 pmcs_fm_fini(pmcs_hw_t *pwp)
3113 {
3114 	/* Only unregister FMA capabilities if registered */
3115 	if (pwp->fm_capabilities) {
3116 		/*
3117 		 * Un-register error callback if error callback capable.
3118 		 */
3119 		if (DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3120 			ddi_fm_handler_unregister(pwp->dip);
3121 		}
3122 
3123 		/*
3124 		 * Release any resources allocated by pci_ereport_setup()
3125 		 */
3126 		if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities) ||
3127 		    DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
3128 			pci_ereport_teardown(pwp->dip);
3129 		}
3130 
3131 		/* Unregister from IO Fault Services */
3132 		ddi_fm_fini(pwp->dip);
3133 
3134 		/* Adjust access and dma attributes for FMA */
3135 		pwp->reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
3136 		pwp->iqp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3137 		pwp->oqp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3138 		pwp->cip_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3139 		pwp->fwlog_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
3140 	}
3141 }
3142 
3143 static boolean_t
3144 pmcs_fabricate_wwid(pmcs_hw_t *pwp)
3145 {
3146 	char *cp, c;
3147 	uint64_t adr;
3148 	int i;
3149 
3150 	cp = &c;
3151 	(void) ddi_strtoul(hw_serial, &cp, 10, (unsigned long *)&adr);
3152 
3153 	if (adr == 0) {
3154 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
3155 		    "%s: No serial number available to fabricate WWN",
3156 		    __func__);
3157 
3158 		adr = (uint64_t)gethrtime();
3159 	}
3160 
3161 	adr <<= 8;
3162 	adr |= ((uint64_t)ddi_get_instance(pwp->dip) << 52);
3163 	adr |= (5ULL << 60);
3164 
3165 	for (i = 0; i < PMCS_MAX_PORTS; i++) {
3166 		pwp->sas_wwns[i] = adr + i;
3167 	}
3168 
3169 	return (B_TRUE);
3170 }
3171