xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_subr.c (revision 658280b6253b61dbb155f43d0e3cbcffa85ccb90)
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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 /*
26  * This file contains various support routines.
27  */
28 
29 #include <sys/scsi/adapters/pmcs/pmcs.h>
30 
31 /*
32  * Local static data
33  */
34 static int tgtmap_usec = MICROSEC;
35 
36 /*
37  * SAS Topology Configuration
38  */
39 static void pmcs_new_tport(pmcs_hw_t *, pmcs_phy_t *);
40 static void pmcs_configure_expander(pmcs_hw_t *, pmcs_phy_t *, pmcs_iport_t *);
41 
42 static void pmcs_check_expanders(pmcs_hw_t *, pmcs_phy_t *);
43 static void pmcs_check_expander(pmcs_hw_t *, pmcs_phy_t *);
44 static void pmcs_clear_expander(pmcs_hw_t *, pmcs_phy_t *, int);
45 
46 static int pmcs_expander_get_nphy(pmcs_hw_t *, pmcs_phy_t *);
47 static int pmcs_expander_content_discover(pmcs_hw_t *, pmcs_phy_t *,
48     pmcs_phy_t *);
49 
50 static int pmcs_smp_function_result(pmcs_hw_t *, smp_response_frame_t *);
51 static boolean_t pmcs_validate_devid(pmcs_phy_t *, pmcs_phy_t *, uint32_t);
52 static void pmcs_clear_phys(pmcs_hw_t *, pmcs_phy_t *);
53 static int pmcs_configure_new_devices(pmcs_hw_t *, pmcs_phy_t *);
54 static void pmcs_begin_observations(pmcs_hw_t *);
55 static void pmcs_flush_observations(pmcs_hw_t *);
56 static boolean_t pmcs_report_observations(pmcs_hw_t *);
57 static boolean_t pmcs_report_iport_observations(pmcs_hw_t *, pmcs_iport_t *,
58     pmcs_phy_t *);
59 static pmcs_phy_t *pmcs_find_phy_needing_work(pmcs_hw_t *, pmcs_phy_t *);
60 static int pmcs_kill_devices(pmcs_hw_t *, pmcs_phy_t *);
61 static void pmcs_lock_phy_impl(pmcs_phy_t *, int);
62 static void pmcs_unlock_phy_impl(pmcs_phy_t *, int);
63 static pmcs_phy_t *pmcs_clone_phy(pmcs_phy_t *);
64 static boolean_t pmcs_configure_phy(pmcs_hw_t *, pmcs_phy_t *);
65 static void pmcs_reap_dead_phy(pmcs_phy_t *);
66 static pmcs_iport_t *pmcs_get_iport_by_ua(pmcs_hw_t *, char *);
67 static boolean_t pmcs_phy_target_match(pmcs_phy_t *);
68 static void pmcs_iport_active(pmcs_iport_t *);
69 static void pmcs_tgtmap_activate_cb(void *, char *, scsi_tgtmap_tgt_type_t,
70     void **);
71 static boolean_t pmcs_tgtmap_deactivate_cb(void *, char *,
72     scsi_tgtmap_tgt_type_t, void *, scsi_tgtmap_deact_rsn_t);
73 static void pmcs_add_dead_phys(pmcs_hw_t *, pmcs_phy_t *);
74 static void pmcs_get_fw_version(pmcs_hw_t *);
75 
76 /*
77  * Often used strings
78  */
79 const char pmcs_nowrk[] = "%s: unable to get work structure";
80 const char pmcs_nomsg[] = "%s: unable to get Inbound Message entry";
81 const char pmcs_timeo[] = "%s: command timed out";
82 
83 extern const ddi_dma_attr_t pmcs_dattr;
84 
85 /*
86  * Some Initial setup steps.
87  */
88 
89 int
90 pmcs_setup(pmcs_hw_t *pwp)
91 {
92 	uint32_t barval = pwp->mpibar;
93 	uint32_t i, scratch, regbar, regoff, barbar, baroff;
94 	uint32_t new_ioq_depth, ferr = 0;
95 
96 	/*
97 	 * Check current state. If we're not at READY state,
98 	 * we can't go further.
99 	 */
100 	scratch = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
101 	if ((scratch & PMCS_MSGU_AAP_STATE_MASK) == PMCS_MSGU_AAP_STATE_ERROR) {
102 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
103 		    "%s: AAP Error State (0x%x)",
104 		    __func__, pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
105 		    PMCS_MSGU_AAP_ERROR_MASK);
106 		pmcs_fm_ereport(pwp, DDI_FM_DEVICE_INVAL_STATE);
107 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
108 		return (-1);
109 	}
110 	if ((scratch & PMCS_MSGU_AAP_STATE_MASK) != PMCS_MSGU_AAP_STATE_READY) {
111 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
112 		    "%s: AAP unit not ready (state 0x%x)",
113 		    __func__, scratch & PMCS_MSGU_AAP_STATE_MASK);
114 		pmcs_fm_ereport(pwp, DDI_FM_DEVICE_INVAL_STATE);
115 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
116 		return (-1);
117 	}
118 
119 	/*
120 	 * Read the offset from the Message Unit scratchpad 0 register.
121 	 * This allows us to read the MPI Configuration table.
122 	 *
123 	 * Check its signature for validity.
124 	 */
125 	baroff = barval;
126 	barbar = barval >> PMCS_MSGU_MPI_BAR_SHIFT;
127 	baroff &= PMCS_MSGU_MPI_OFFSET_MASK;
128 
129 	regoff = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0);
130 	regbar = regoff >> PMCS_MSGU_MPI_BAR_SHIFT;
131 	regoff &= PMCS_MSGU_MPI_OFFSET_MASK;
132 
133 	if (regoff > baroff) {
134 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
135 		    "%s: bad MPI Table Length (register offset=0x%08x, "
136 		    "passed offset=0x%08x)", __func__, regoff, baroff);
137 		return (-1);
138 	}
139 	if (regbar != barbar) {
140 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
141 		    "%s: bad MPI BAR (register BAROFF=0x%08x, "
142 		    "passed BAROFF=0x%08x)", __func__, regbar, barbar);
143 		return (-1);
144 	}
145 	pwp->mpi_offset = regoff;
146 	if (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS) != PMCS_SIGNATURE) {
147 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
148 		    "%s: Bad MPI Configuration Table Signature 0x%x", __func__,
149 		    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS));
150 		return (-1);
151 	}
152 
153 	if (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IR) != PMCS_MPI_REVISION1) {
154 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
155 		    "%s: Bad MPI Configuration Revision 0x%x", __func__,
156 		    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IR));
157 		return (-1);
158 	}
159 
160 	/*
161 	 * Generate offsets for the General System, Inbound Queue Configuration
162 	 * and Outbound Queue configuration tables. This way the macros to
163 	 * access those tables will work correctly.
164 	 */
165 	pwp->mpi_gst_offset =
166 	    pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO);
167 	pwp->mpi_iqc_offset =
168 	    pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO);
169 	pwp->mpi_oqc_offset =
170 	    pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO);
171 
172 	pmcs_get_fw_version(pwp);
173 
174 	pwp->max_cmd = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO);
175 	pwp->max_dev = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0) >> 16;
176 
177 	pwp->max_iq = PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
178 	pwp->max_oq = PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
179 	pwp->nphy = PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
180 	if (pwp->max_iq <= PMCS_NIQ) {
181 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
182 		    "%s: not enough Inbound Queues supported "
183 		    "(need %d, max_oq=%d)", __func__, pwp->max_iq, PMCS_NIQ);
184 		return (-1);
185 	}
186 	if (pwp->max_oq <= PMCS_NOQ) {
187 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
188 		    "%s: not enough Outbound Queues supported "
189 		    "(need %d, max_oq=%d)", __func__, pwp->max_oq, PMCS_NOQ);
190 		return (-1);
191 	}
192 	if (pwp->nphy == 0) {
193 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
194 		    "%s: zero phys reported", __func__);
195 		return (-1);
196 	}
197 	if (PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))) {
198 		pwp->hipri_queue = (1 << PMCS_IQ_OTHER);
199 	}
200 
201 
202 	for (i = 0; i < pwp->nphy; i++) {
203 		PMCS_MPI_EVQSET(pwp, PMCS_OQ_EVENTS, i);
204 		PMCS_MPI_NCQSET(pwp, PMCS_OQ_EVENTS, i);
205 	}
206 
207 	pmcs_wr_mpi_tbl(pwp, PMCS_MPI_INFO2,
208 	    (PMCS_OQ_EVENTS << GENERAL_EVENT_OQ_SHIFT) |
209 	    (PMCS_OQ_EVENTS << DEVICE_HANDLE_REMOVED_SHIFT));
210 
211 	/*
212 	 * Verify that ioq_depth is valid (> 0 and not so high that it
213 	 * would cause us to overrun the chip with commands).
214 	 */
215 	if (pwp->ioq_depth == 0) {
216 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
217 		    "%s: I/O queue depth set to 0. Setting to %d",
218 		    __func__, PMCS_NQENTRY);
219 		pwp->ioq_depth = PMCS_NQENTRY;
220 	}
221 
222 	if (pwp->ioq_depth < PMCS_MIN_NQENTRY) {
223 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
224 		    "%s: I/O queue depth set too low (%d). Setting to %d",
225 		    __func__, pwp->ioq_depth, PMCS_MIN_NQENTRY);
226 		pwp->ioq_depth = PMCS_MIN_NQENTRY;
227 	}
228 
229 	if (pwp->ioq_depth > (pwp->max_cmd / (PMCS_IO_IQ_MASK + 1))) {
230 		new_ioq_depth = pwp->max_cmd / (PMCS_IO_IQ_MASK + 1);
231 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
232 		    "%s: I/O queue depth set too high (%d). Setting to %d",
233 		    __func__, pwp->ioq_depth, new_ioq_depth);
234 		pwp->ioq_depth = new_ioq_depth;
235 	}
236 
237 	/*
238 	 * Allocate consistent memory for OQs and IQs.
239 	 */
240 	pwp->iqp_dma_attr = pwp->oqp_dma_attr = pmcs_dattr;
241 	pwp->iqp_dma_attr.dma_attr_align =
242 	    pwp->oqp_dma_attr.dma_attr_align = PMCS_QENTRY_SIZE;
243 
244 	/*
245 	 * The Rev C chip has the ability to do PIO to or from consistent
246 	 * memory anywhere in a 64 bit address space, but the firmware is
247 	 * not presently set up to do so.
248 	 */
249 	pwp->iqp_dma_attr.dma_attr_addr_hi =
250 	    pwp->oqp_dma_attr.dma_attr_addr_hi = 0x000000FFFFFFFFFFull;
251 
252 	for (i = 0; i < PMCS_NIQ; i++) {
253 		if (pmcs_dma_setup(pwp, &pwp->iqp_dma_attr,
254 		    &pwp->iqp_acchdls[i],
255 		    &pwp->iqp_handles[i], PMCS_QENTRY_SIZE * pwp->ioq_depth,
256 		    (caddr_t *)&pwp->iqp[i], &pwp->iqaddr[i]) == B_FALSE) {
257 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
258 			    "Failed to setup DMA for iqp[%d]", i);
259 			return (-1);
260 		}
261 		bzero(pwp->iqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
262 	}
263 
264 	for (i = 0; i < PMCS_NOQ; i++) {
265 		if (pmcs_dma_setup(pwp, &pwp->oqp_dma_attr,
266 		    &pwp->oqp_acchdls[i],
267 		    &pwp->oqp_handles[i], PMCS_QENTRY_SIZE * pwp->ioq_depth,
268 		    (caddr_t *)&pwp->oqp[i], &pwp->oqaddr[i]) == B_FALSE) {
269 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
270 			    "Failed to setup DMA for oqp[%d]", i);
271 			return (-1);
272 		}
273 		bzero(pwp->oqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
274 	}
275 
276 	/*
277 	 * Install the IQ and OQ addresses (and null out the rest).
278 	 */
279 	for (i = 0; i < pwp->max_iq; i++) {
280 		pwp->iqpi_offset[i] = pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i));
281 		if (i < PMCS_NIQ) {
282 			if (i != PMCS_IQ_OTHER) {
283 				pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i),
284 				    pwp->ioq_depth | (PMCS_QENTRY_SIZE << 16));
285 			} else {
286 				pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i),
287 				    (1 << 30) | pwp->ioq_depth |
288 				    (PMCS_QENTRY_SIZE << 16));
289 			}
290 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i),
291 			    DWORD1(pwp->iqaddr[i]));
292 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i),
293 			    DWORD0(pwp->iqaddr[i]));
294 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i),
295 			    DWORD1(pwp->ciaddr+IQ_OFFSET(i)));
296 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i),
297 			    DWORD0(pwp->ciaddr+IQ_OFFSET(i)));
298 		} else {
299 			pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i), 0);
300 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i), 0);
301 			pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i), 0);
302 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i), 0);
303 			pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i), 0);
304 		}
305 	}
306 
307 	for (i = 0; i < pwp->max_oq; i++) {
308 		pwp->oqci_offset[i] = pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i));
309 		if (i < PMCS_NOQ) {
310 			pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), pwp->ioq_depth |
311 			    (PMCS_QENTRY_SIZE << 16) | OQIEX);
312 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i),
313 			    DWORD1(pwp->oqaddr[i]));
314 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i),
315 			    DWORD0(pwp->oqaddr[i]));
316 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i),
317 			    DWORD1(pwp->ciaddr+OQ_OFFSET(i)));
318 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i),
319 			    DWORD0(pwp->ciaddr+OQ_OFFSET(i)));
320 			pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i),
321 			    pwp->oqvec[i] << 24);
322 			pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
323 		} else {
324 			pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), 0);
325 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i), 0);
326 			pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i), 0);
327 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i), 0);
328 			pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i), 0);
329 			pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i), 0);
330 			pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
331 		}
332 	}
333 
334 	/*
335 	 * Set up logging, if defined.
336 	 */
337 	if (pwp->fwlog) {
338 		uint64_t logdma = pwp->fwaddr;
339 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBAH, DWORD1(logdma));
340 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBAL, DWORD0(logdma));
341 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBS, PMCS_FWLOG_SIZE >> 1);
342 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELSEV, pwp->fwlog);
343 		logdma += (PMCS_FWLOG_SIZE >> 1);
344 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBAH, DWORD1(logdma));
345 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBAL, DWORD0(logdma));
346 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBS, PMCS_FWLOG_SIZE >> 1);
347 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELSEV, pwp->fwlog);
348 	}
349 
350 	/*
351 	 * Interrupt vectors, outbound queues, and odb_auto_clear
352 	 *
353 	 * MSI/MSI-X:
354 	 * If we got 4 interrupt vectors, we'll assign one to each outbound
355 	 * queue as well as the fatal interrupt, and auto clear can be set
356 	 * for each.
357 	 *
358 	 * If we only got 2 vectors, one will be used for I/O completions
359 	 * and the other for the other two vectors.  In this case, auto_
360 	 * clear can only be set for I/Os, which is fine.  The fatal
361 	 * interrupt will be mapped to the PMCS_FATAL_INTERRUPT bit, which
362 	 * is not an interrupt vector.
363 	 *
364 	 * MSI/MSI-X/INT-X:
365 	 * If we only got 1 interrupt vector, auto_clear must be set to 0,
366 	 * and again the fatal interrupt will be mapped to the
367 	 * PMCS_FATAL_INTERRUPT bit (again, not an interrupt vector).
368 	 */
369 
370 	switch (pwp->int_type) {
371 	case PMCS_INT_MSIX:
372 	case PMCS_INT_MSI:
373 		switch (pwp->intr_cnt) {
374 		case 1:
375 			pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
376 			    (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
377 			pwp->odb_auto_clear = 0;
378 			break;
379 		case 2:
380 			pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
381 			    (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
382 			pwp->odb_auto_clear = (1 << PMCS_FATAL_INTERRUPT) |
383 			    (1 << PMCS_MSIX_IODONE);
384 			break;
385 		case 4:
386 			pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
387 			    (PMCS_MSIX_FATAL << PMCS_FERIV_SHIFT));
388 			pwp->odb_auto_clear = (1 << PMCS_MSIX_FATAL) |
389 			    (1 << PMCS_MSIX_GENERAL) | (1 << PMCS_MSIX_IODONE) |
390 			    (1 << PMCS_MSIX_EVENTS);
391 			break;
392 		}
393 		break;
394 
395 	case PMCS_INT_FIXED:
396 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR,
397 		    PMCS_FERRIE | (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
398 		pwp->odb_auto_clear = 0;
399 		break;
400 	}
401 
402 	/*
403 	 * If the open retry interval is non-zero, set it.
404 	 */
405 	if (pwp->open_retry_interval != 0) {
406 		int phynum;
407 
408 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
409 		    "%s: Setting open retry interval to %d usecs", __func__,
410 		    pwp->open_retry_interval);
411 		for (phynum = 0; phynum < pwp->nphy; phynum ++) {
412 			pmcs_wr_gsm_reg(pwp, OPEN_RETRY_INTERVAL(phynum),
413 			    pwp->open_retry_interval);
414 		}
415 	}
416 
417 	/*
418 	 * Enable Interrupt Reassertion
419 	 * Default Delay 1000us
420 	 */
421 	ferr = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR);
422 	if ((ferr & PMCS_MPI_IRAE) == 0) {
423 		ferr &= ~(PMCS_MPI_IRAU | PMCS_MPI_IRAD_MASK);
424 		pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, ferr | PMCS_MPI_IRAE);
425 	}
426 
427 	pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR, pwp->odb_auto_clear);
428 	pwp->mpi_table_setup = 1;
429 	return (0);
430 }
431 
432 /*
433  * Start the Message Passing protocol with the PMC chip.
434  */
435 int
436 pmcs_start_mpi(pmcs_hw_t *pwp)
437 {
438 	int i;
439 
440 	pmcs_wr_msgunit(pwp, PMCS_MSGU_IBDB, PMCS_MSGU_IBDB_MPIINI);
441 	for (i = 0; i < 1000; i++) {
442 		if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) &
443 		    PMCS_MSGU_IBDB_MPIINI) == 0) {
444 			break;
445 		}
446 		drv_usecwait(1000);
447 	}
448 	if (pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) & PMCS_MSGU_IBDB_MPIINI) {
449 		return (-1);
450 	}
451 	drv_usecwait(500000);
452 
453 	/*
454 	 * Check to make sure we got to INIT state.
455 	 */
456 	if (PMCS_MPI_S(pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE)) !=
457 	    PMCS_MPI_STATE_INIT) {
458 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
459 		    "%s: MPI launch failed (GST 0x%x DBCLR 0x%x)", __func__,
460 		    pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE),
461 		    pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR));
462 		return (-1);
463 	}
464 	return (0);
465 }
466 
467 /*
468  * Stop the Message Passing protocol with the PMC chip.
469  */
470 int
471 pmcs_stop_mpi(pmcs_hw_t *pwp)
472 {
473 	int i;
474 
475 	for (i = 0; i < pwp->max_iq; i++) {
476 		pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i), 0);
477 		pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i), 0);
478 		pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i), 0);
479 		pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i), 0);
480 		pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i), 0);
481 	}
482 	for (i = 0; i < pwp->max_oq; i++) {
483 		pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), 0);
484 		pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i), 0);
485 		pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i), 0);
486 		pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i), 0);
487 		pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i), 0);
488 		pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i), 0);
489 		pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
490 	}
491 	pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, 0);
492 	pmcs_wr_msgunit(pwp, PMCS_MSGU_IBDB, PMCS_MSGU_IBDB_MPICTU);
493 	for (i = 0; i < 2000; i++) {
494 		if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) &
495 		    PMCS_MSGU_IBDB_MPICTU) == 0) {
496 			break;
497 		}
498 		drv_usecwait(1000);
499 	}
500 	if (pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) & PMCS_MSGU_IBDB_MPICTU) {
501 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
502 		    "%s: MPI stop failed", __func__);
503 		return (-1);
504 	}
505 	return (0);
506 }
507 
508 /*
509  * Do a sequence of ECHO messages to test for MPI functionality,
510  * all inbound and outbound queue functionality and interrupts.
511  */
512 int
513 pmcs_echo_test(pmcs_hw_t *pwp)
514 {
515 	echo_test_t fred;
516 	struct pmcwork *pwrk;
517 	uint32_t *msg, count;
518 	int iqe = 0, iqo = 0, result, rval = 0;
519 	int iterations;
520 	hrtime_t echo_start, echo_end, echo_total;
521 
522 	ASSERT(pwp->max_cmd > 0);
523 
524 	/*
525 	 * We want iterations to be max_cmd * 3 to ensure that we run the
526 	 * echo test enough times to iterate through every inbound queue
527 	 * at least twice.
528 	 */
529 	iterations = pwp->max_cmd * 3;
530 
531 	echo_total = 0;
532 	count = 0;
533 
534 	while (count < iterations) {
535 		pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
536 		if (pwrk == NULL) {
537 			pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
538 			    pmcs_nowrk, __func__);
539 			rval = -1;
540 			break;
541 		}
542 
543 		mutex_enter(&pwp->iqp_lock[iqe]);
544 		msg = GET_IQ_ENTRY(pwp, iqe);
545 		if (msg == NULL) {
546 			mutex_exit(&pwp->iqp_lock[iqe]);
547 			pmcs_pwork(pwp, pwrk);
548 			pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
549 			    pmcs_nomsg, __func__);
550 			rval = -1;
551 			break;
552 		}
553 
554 		bzero(msg, PMCS_QENTRY_SIZE);
555 
556 		if (iqe == PMCS_IQ_OTHER) {
557 			/* This is on the high priority queue */
558 			msg[0] = LE_32(PMCS_HIPRI(pwp, iqo, PMCIN_ECHO));
559 		} else {
560 			msg[0] = LE_32(PMCS_IOMB_IN_SAS(iqo, PMCIN_ECHO));
561 		}
562 		msg[1] = LE_32(pwrk->htag);
563 		fred.signature = 0xdeadbeef;
564 		fred.count = count;
565 		fred.ptr = &count;
566 		(void) memcpy(&msg[2], &fred, sizeof (fred));
567 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
568 
569 		INC_IQ_ENTRY(pwp, iqe);
570 
571 		echo_start = gethrtime();
572 		DTRACE_PROBE2(pmcs__echo__test__wait__start,
573 		    hrtime_t, echo_start, uint32_t, pwrk->htag);
574 
575 		if (++iqe == PMCS_NIQ) {
576 			iqe = 0;
577 		}
578 		if (++iqo == PMCS_NOQ) {
579 			iqo = 0;
580 		}
581 
582 		WAIT_FOR(pwrk, 250, result);
583 
584 		echo_end = gethrtime();
585 		DTRACE_PROBE2(pmcs__echo__test__wait__end,
586 		    hrtime_t, echo_end, int, result);
587 
588 		echo_total += (echo_end - echo_start);
589 
590 		pmcs_pwork(pwp, pwrk);
591 		if (result) {
592 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
593 			    "%s: command timed out on echo test #%d",
594 			    __func__, count);
595 			rval = -1;
596 			break;
597 		}
598 	}
599 
600 	/*
601 	 * The intr_threshold is adjusted by PMCS_INTR_THRESHOLD in order to
602 	 * remove the overhead of things like the delay in getting signaled
603 	 * for completion.
604 	 */
605 	if (echo_total != 0) {
606 		pwp->io_intr_coal.intr_latency =
607 		    (echo_total / iterations) / 2;
608 		pwp->io_intr_coal.intr_threshold =
609 		    PMCS_INTR_THRESHOLD(PMCS_QUANTUM_TIME_USECS * 1000 /
610 		    pwp->io_intr_coal.intr_latency);
611 	}
612 
613 	return (rval);
614 }
615 
616 /*
617  * Start the (real) phys
618  */
619 int
620 pmcs_start_phy(pmcs_hw_t *pwp, int phynum, int linkmode, int speed)
621 {
622 	int result;
623 	uint32_t *msg;
624 	struct pmcwork *pwrk;
625 	pmcs_phy_t *pptr;
626 	sas_identify_af_t sap;
627 
628 	mutex_enter(&pwp->lock);
629 	pptr = pwp->root_phys + phynum;
630 	if (pptr == NULL) {
631 		mutex_exit(&pwp->lock);
632 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
633 		    "%s: cannot find port %d", __func__, phynum);
634 		return (0);
635 	}
636 
637 	pmcs_lock_phy(pptr);
638 	mutex_exit(&pwp->lock);
639 
640 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
641 	if (pwrk == NULL) {
642 		pmcs_unlock_phy(pptr);
643 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
644 		return (-1);
645 	}
646 
647 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
648 	msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
649 
650 	if (msg == NULL) {
651 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
652 		pmcs_unlock_phy(pptr);
653 		pmcs_pwork(pwp, pwrk);
654 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
655 		return (-1);
656 	}
657 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_PHY_START));
658 	msg[1] = LE_32(pwrk->htag);
659 	msg[2] = LE_32(linkmode | speed | phynum);
660 	bzero(&sap, sizeof (sap));
661 	sap.device_type = SAS_IF_DTYPE_ENDPOINT;
662 	sap.ssp_ini_port = 1;
663 
664 	if (pwp->separate_ports) {
665 		pmcs_wwn2barray(pwp->sas_wwns[phynum], sap.sas_address);
666 	} else {
667 		pmcs_wwn2barray(pwp->sas_wwns[0], sap.sas_address);
668 	}
669 
670 	ASSERT(phynum < SAS2_PHYNUM_MAX);
671 	sap.phy_identifier = phynum & SAS2_PHYNUM_MASK;
672 	(void) memcpy(&msg[3], &sap, sizeof (sas_identify_af_t));
673 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
674 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
675 
676 	pptr->state.prog_min_rate = (lowbit((ulong_t)speed) - 1);
677 	pptr->state.prog_max_rate = (highbit((ulong_t)speed) - 1);
678 	pptr->state.hw_min_rate = PMCS_HW_MIN_LINK_RATE;
679 	pptr->state.hw_max_rate = PMCS_HW_MAX_LINK_RATE;
680 
681 	pmcs_unlock_phy(pptr);
682 	WAIT_FOR(pwrk, 1000, result);
683 	pmcs_pwork(pwp, pwrk);
684 
685 	if (result) {
686 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, pmcs_timeo, __func__);
687 	} else {
688 		mutex_enter(&pwp->lock);
689 		pwp->phys_started |= (1 << phynum);
690 		mutex_exit(&pwp->lock);
691 	}
692 
693 	return (0);
694 }
695 
696 int
697 pmcs_start_phys(pmcs_hw_t *pwp)
698 {
699 	int i;
700 
701 	for (i = 0; i < pwp->nphy; i++) {
702 		if ((pwp->phyid_block_mask & (1 << i)) == 0) {
703 			if (pmcs_start_phy(pwp, i,
704 			    (pwp->phymode << PHY_MODE_SHIFT),
705 			    pwp->physpeed << PHY_LINK_SHIFT)) {
706 				return (-1);
707 			}
708 			if (pmcs_clear_diag_counters(pwp, i)) {
709 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
710 				    "%s: failed to reset counters on PHY (%d)",
711 				    __func__, i);
712 			}
713 		}
714 	}
715 	return (0);
716 }
717 
718 /*
719  * Called with PHY locked
720  */
721 int
722 pmcs_reset_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint8_t type)
723 {
724 	uint32_t *msg;
725 	uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
726 	const char *mbar;
727 	uint32_t amt;
728 	uint32_t pdevid;
729 	uint32_t stsoff;
730 	uint32_t status;
731 	int result, level, phynum;
732 	struct pmcwork *pwrk;
733 	uint32_t htag;
734 
735 	ASSERT(mutex_owned(&pptr->phy_lock));
736 
737 	bzero(iomb, PMCS_QENTRY_SIZE);
738 	phynum = pptr->phynum;
739 	level = pptr->level;
740 	if (level > 0) {
741 		pdevid = pptr->parent->device_id;
742 	} else if ((level == 0) && (pptr->dtype == EXPANDER)) {
743 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, pptr->target,
744 		    "%s: Not resetting HBA PHY @ %s", __func__, pptr->path);
745 		return (0);
746 	}
747 
748 	if (!pptr->iport || !pptr->valid_device_id) {
749 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, pptr->target,
750 		    "%s: Can't reach PHY %s", __func__, pptr->path);
751 		return (0);
752 	}
753 
754 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
755 
756 	if (pwrk == NULL) {
757 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
758 		return (ENOMEM);
759 	}
760 
761 	pwrk->arg = iomb;
762 
763 	/*
764 	 * If level > 0, we need to issue an SMP_REQUEST with a PHY_CONTROL
765 	 * function to do either a link reset or hard reset.  If level == 0,
766 	 * then we do a LOCAL_PHY_CONTROL IOMB to do link/hard reset to the
767 	 * root (local) PHY
768 	 */
769 	if (level) {
770 		stsoff = 2;
771 		iomb[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
772 		    PMCIN_SMP_REQUEST));
773 		iomb[1] = LE_32(pwrk->htag);
774 		iomb[2] = LE_32(pdevid);
775 		iomb[3] = LE_32(40 << SMP_REQUEST_LENGTH_SHIFT);
776 		/*
777 		 * Send SMP PHY CONTROL/HARD or LINK RESET
778 		 */
779 		iomb[4] = BE_32(0x40910000);
780 		iomb[5] = 0;
781 
782 		if (type == PMCS_PHYOP_HARD_RESET) {
783 			mbar = "SMP PHY CONTROL/HARD RESET";
784 			iomb[6] = BE_32((phynum << 24) |
785 			    (PMCS_PHYOP_HARD_RESET << 16));
786 		} else {
787 			mbar = "SMP PHY CONTROL/LINK RESET";
788 			iomb[6] = BE_32((phynum << 24) |
789 			    (PMCS_PHYOP_LINK_RESET << 16));
790 		}
791 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
792 		    "%s: sending %s to %s for phy 0x%x",
793 		    __func__, mbar, pptr->parent->path, pptr->phynum);
794 		amt = 7;
795 	} else {
796 		/*
797 		 * Unlike most other Outbound messages, status for
798 		 * a local phy operation is in DWORD 3.
799 		 */
800 		stsoff = 3;
801 		iomb[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
802 		    PMCIN_LOCAL_PHY_CONTROL));
803 		iomb[1] = LE_32(pwrk->htag);
804 		if (type == PMCS_PHYOP_LINK_RESET) {
805 			mbar = "LOCAL PHY LINK RESET";
806 			iomb[2] = LE_32((PMCS_PHYOP_LINK_RESET << 8) | phynum);
807 		} else {
808 			mbar = "LOCAL PHY HARD RESET";
809 			iomb[2] = LE_32((PMCS_PHYOP_HARD_RESET << 8) | phynum);
810 		}
811 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
812 		    "%s: sending %s to %s", __func__, mbar, pptr->path);
813 		amt = 3;
814 	}
815 
816 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
817 	msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
818 	if (msg == NULL) {
819 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
820 		pmcs_pwork(pwp, pwrk);
821 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
822 		return (ENOMEM);
823 	}
824 	COPY_MESSAGE(msg, iomb, amt);
825 	htag = pwrk->htag;
826 
827 	/* SMP serialization */
828 	pmcs_smp_acquire(pptr->iport);
829 
830 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
831 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
832 
833 	pmcs_unlock_phy(pptr);
834 	WAIT_FOR(pwrk, 1000, result);
835 	pmcs_pwork(pwp, pwrk);
836 	/* Release SMP lock before reacquiring PHY lock */
837 	pmcs_smp_release(pptr->iport);
838 	pmcs_lock_phy(pptr);
839 
840 	if (result) {
841 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, pmcs_timeo, __func__);
842 
843 		if (pmcs_abort(pwp, pptr, htag, 0, 0)) {
844 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
845 			    "%s: Unable to issue SMP abort for htag 0x%08x",
846 			    __func__, htag);
847 		} else {
848 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
849 			    "%s: Issuing SMP ABORT for htag 0x%08x",
850 			    __func__, htag);
851 		}
852 		return (EIO);
853 	}
854 	status = LE_32(iomb[stsoff]);
855 
856 	if (status != PMCOUT_STATUS_OK) {
857 		char buf[32];
858 		const char *es =  pmcs_status_str(status);
859 		if (es == NULL) {
860 			(void) snprintf(buf, sizeof (buf), "Status 0x%x",
861 			    status);
862 			es = buf;
863 		}
864 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
865 		    "%s: %s action returned %s for %s", __func__, mbar, es,
866 		    pptr->path);
867 		return (status);
868 	}
869 
870 	return (0);
871 }
872 
873 /*
874  * Stop the (real) phys.  No PHY or softstate locks are required as this only
875  * happens during detach.
876  */
877 void
878 pmcs_stop_phy(pmcs_hw_t *pwp, int phynum)
879 {
880 	int result;
881 	pmcs_phy_t *pptr;
882 	uint32_t *msg;
883 	struct pmcwork *pwrk;
884 
885 	pptr =  pwp->root_phys + phynum;
886 	if (pptr == NULL) {
887 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
888 		    "%s: unable to find port %d", __func__, phynum);
889 		return;
890 	}
891 
892 	if (pwp->phys_started & (1 << phynum)) {
893 		pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
894 
895 		if (pwrk == NULL) {
896 			pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL,
897 			    pmcs_nowrk, __func__);
898 			return;
899 		}
900 
901 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
902 		msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
903 
904 		if (msg == NULL) {
905 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
906 			pmcs_pwork(pwp, pwrk);
907 			pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL,
908 			    pmcs_nomsg, __func__);
909 			return;
910 		}
911 
912 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_PHY_STOP));
913 		msg[1] = LE_32(pwrk->htag);
914 		msg[2] = LE_32(phynum);
915 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
916 		/*
917 		 * Make this unconfigured now.
918 		 */
919 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
920 		WAIT_FOR(pwrk, 1000, result);
921 
922 		pmcs_pwork(pwp, pwrk);
923 		if (result) {
924 			pmcs_prt(pwp, PMCS_PRT_DEBUG,
925 			    pptr, NULL, pmcs_timeo, __func__);
926 		}
927 
928 		pwp->phys_started &= ~(1 << phynum);
929 	}
930 
931 	pptr->configured = 0;
932 }
933 
934 /*
935  * No locks should be required as this is only called during detach
936  */
937 void
938 pmcs_stop_phys(pmcs_hw_t *pwp)
939 {
940 	int i;
941 	for (i = 0; i < pwp->nphy; i++) {
942 		if ((pwp->phyid_block_mask & (1 << i)) == 0) {
943 			pmcs_stop_phy(pwp, i);
944 		}
945 	}
946 }
947 
948 /*
949  * Run SAS_DIAG_EXECUTE with cmd and cmd_desc passed.
950  * 	ERR_CNT_RESET: return status of cmd
951  *	DIAG_REPORT_GET: return value of the counter
952  */
953 int
954 pmcs_sas_diag_execute(pmcs_hw_t *pwp, uint32_t cmd, uint32_t cmd_desc,
955     uint8_t phynum)
956 {
957 	uint32_t htag, *ptr, status, msg[PMCS_MSG_SIZE << 1];
958 	int result;
959 	struct pmcwork *pwrk;
960 
961 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
962 	if (pwrk == NULL) {
963 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nowrk, __func__);
964 		return (DDI_FAILURE);
965 	}
966 	pwrk->arg = msg;
967 	htag = pwrk->htag;
968 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_SAS_DIAG_EXECUTE));
969 	msg[1] = LE_32(htag);
970 	msg[2] = LE_32((cmd << PMCS_DIAG_CMD_SHIFT) |
971 	    (cmd_desc << PMCS_DIAG_CMD_DESC_SHIFT) | phynum);
972 
973 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
974 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
975 	if (ptr == NULL) {
976 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
977 		pmcs_pwork(pwp, pwrk);
978 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nomsg, __func__);
979 		return (DDI_FAILURE);
980 	}
981 	COPY_MESSAGE(ptr, msg, 3);
982 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
983 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
984 
985 	WAIT_FOR(pwrk, 1000, result);
986 
987 	pmcs_pwork(pwp, pwrk);
988 
989 	if (result) {
990 		pmcs_timed_out(pwp, htag, __func__);
991 		return (DDI_FAILURE);
992 	}
993 
994 	status = LE_32(msg[3]);
995 
996 	/* Return for counter reset */
997 	if (cmd == PMCS_ERR_CNT_RESET)
998 		return (status);
999 
1000 	/* Return for counter value */
1001 	if (status) {
1002 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1003 		    "%s: failed, status (0x%x)", __func__, status);
1004 		return (DDI_FAILURE);
1005 	}
1006 	return (LE_32(msg[4]));
1007 }
1008 
1009 /* Get the current value of the counter for desc on phynum and return it. */
1010 int
1011 pmcs_get_diag_report(pmcs_hw_t *pwp, uint32_t desc, uint8_t phynum)
1012 {
1013 	return (pmcs_sas_diag_execute(pwp, PMCS_DIAG_REPORT_GET, desc, phynum));
1014 }
1015 
1016 /* Clear all of the counters for phynum. Returns the status of the command. */
1017 int
1018 pmcs_clear_diag_counters(pmcs_hw_t *pwp, uint8_t phynum)
1019 {
1020 	uint32_t	cmd = PMCS_ERR_CNT_RESET;
1021 	uint32_t	cmd_desc;
1022 
1023 	cmd_desc = PMCS_INVALID_DWORD_CNT;
1024 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
1025 		return (DDI_FAILURE);
1026 
1027 	cmd_desc = PMCS_DISPARITY_ERR_CNT;
1028 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
1029 		return (DDI_FAILURE);
1030 
1031 	cmd_desc = PMCS_LOST_DWORD_SYNC_CNT;
1032 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
1033 		return (DDI_FAILURE);
1034 
1035 	cmd_desc = PMCS_RESET_FAILED_CNT;
1036 	if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
1037 		return (DDI_FAILURE);
1038 
1039 	return (DDI_SUCCESS);
1040 }
1041 
1042 /*
1043  * Get firmware timestamp
1044  */
1045 int
1046 pmcs_get_time_stamp(pmcs_hw_t *pwp, uint64_t *ts)
1047 {
1048 	uint32_t htag, *ptr, msg[PMCS_MSG_SIZE << 1];
1049 	int result;
1050 	struct pmcwork *pwrk;
1051 
1052 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
1053 	if (pwrk == NULL) {
1054 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nowrk, __func__);
1055 		return (-1);
1056 	}
1057 	pwrk->arg = msg;
1058 	htag = pwrk->htag;
1059 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_GET_TIME_STAMP));
1060 	msg[1] = LE_32(pwrk->htag);
1061 
1062 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1063 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1064 	if (ptr == NULL) {
1065 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1066 		pmcs_pwork(pwp, pwrk);
1067 		pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, pmcs_nomsg, __func__);
1068 		return (-1);
1069 	}
1070 	COPY_MESSAGE(ptr, msg, 2);
1071 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
1072 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1073 
1074 	WAIT_FOR(pwrk, 1000, result);
1075 
1076 	pmcs_pwork(pwp, pwrk);
1077 
1078 	if (result) {
1079 		pmcs_timed_out(pwp, htag, __func__);
1080 		return (-1);
1081 	}
1082 	*ts = LE_32(msg[2]) | (((uint64_t)LE_32(msg[3])) << 32);
1083 	return (0);
1084 }
1085 
1086 /*
1087  * Dump all pertinent registers
1088  */
1089 
1090 void
1091 pmcs_register_dump(pmcs_hw_t *pwp)
1092 {
1093 	int i;
1094 	uint32_t val;
1095 
1096 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "pmcs%d: Register dump start",
1097 	    ddi_get_instance(pwp->dip));
1098 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
1099 	    "OBDB (intr): 0x%08x (mask): 0x%08x (clear): 0x%08x",
1100 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB),
1101 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK),
1102 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR));
1103 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH0: 0x%08x",
1104 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0));
1105 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH1: 0x%08x",
1106 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1));
1107 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH2: 0x%08x",
1108 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2));
1109 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "SCRATCH3: 0x%08x",
1110 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3));
1111 	for (i = 0; i < PMCS_NIQ; i++) {
1112 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "IQ %d: CI %u PI %u",
1113 		    i, pmcs_rd_iqci(pwp, i), pmcs_rd_iqpi(pwp, i));
1114 	}
1115 	for (i = 0; i < PMCS_NOQ; i++) {
1116 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "OQ %d: CI %u PI %u",
1117 		    i, pmcs_rd_oqci(pwp, i), pmcs_rd_oqpi(pwp, i));
1118 	}
1119 	val = pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE);
1120 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
1121 	    "GST TABLE BASE: 0x%08x (STATE=0x%x QF=%d GSTLEN=%d HMI_ERR=0x%x)",
1122 	    val, PMCS_MPI_S(val), PMCS_QF(val), PMCS_GSTLEN(val) * 4,
1123 	    PMCS_HMI_ERR(val));
1124 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE IQFRZ0: 0x%08x",
1125 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0));
1126 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE IQFRZ1: 0x%08x",
1127 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1));
1128 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE MSGU TICK: 0x%08x",
1129 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK));
1130 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "GST TABLE IOP TICK: 0x%08x",
1131 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK));
1132 	for (i = 0; i < pwp->nphy; i++) {
1133 		uint32_t rerrf, pinfo, started = 0, link = 0;
1134 		pinfo = pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i));
1135 		if (pinfo & 1) {
1136 			started = 1;
1137 			link = pinfo & 2;
1138 		}
1139 		rerrf = pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i));
1140 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
1141 		    "GST TABLE PHY%d STARTED=%d LINK=%d RERR=0x%08x",
1142 		    i, started, link, rerrf);
1143 	}
1144 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "pmcs%d: Register dump end",
1145 	    ddi_get_instance(pwp->dip));
1146 }
1147 
1148 /*
1149  * Handle SATA Abort and other error processing
1150  */
1151 int
1152 pmcs_abort_handler(pmcs_hw_t *pwp)
1153 {
1154 	pmcs_phy_t *pptr, *pnext, *pnext_uplevel[PMCS_MAX_XPND];
1155 	pmcs_xscsi_t *tgt;
1156 	int r, level = 0;
1157 
1158 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s", __func__);
1159 
1160 	mutex_enter(&pwp->lock);
1161 	pptr = pwp->root_phys;
1162 	mutex_exit(&pwp->lock);
1163 
1164 	while (pptr) {
1165 		/*
1166 		 * XXX: Need to make sure this doesn't happen
1167 		 * XXX: when non-NCQ commands are running.
1168 		 */
1169 		pmcs_lock_phy(pptr);
1170 		if (pptr->need_rl_ext) {
1171 			ASSERT(pptr->dtype == SATA);
1172 			if (pmcs_acquire_scratch(pwp, B_FALSE)) {
1173 				goto next_phy;
1174 			}
1175 			r = pmcs_sata_abort_ncq(pwp, pptr);
1176 			pmcs_release_scratch(pwp);
1177 			if (r == ENOMEM) {
1178 				goto next_phy;
1179 			}
1180 			if (r) {
1181 				r = pmcs_reset_phy(pwp, pptr,
1182 				    PMCS_PHYOP_LINK_RESET);
1183 				if (r == ENOMEM) {
1184 					goto next_phy;
1185 				}
1186 				/* what if other failures happened? */
1187 				pptr->abort_pending = 1;
1188 				pptr->abort_sent = 0;
1189 			}
1190 		}
1191 		if (pptr->abort_pending == 0 || pptr->abort_sent) {
1192 			goto next_phy;
1193 		}
1194 		pptr->abort_pending = 0;
1195 		if (pmcs_abort(pwp, pptr, pptr->device_id, 1, 1) == ENOMEM) {
1196 			pptr->abort_pending = 1;
1197 			goto next_phy;
1198 		}
1199 		pptr->abort_sent = 1;
1200 
1201 		/*
1202 		 * If the iport is no longer active, flush the queues
1203 		 */
1204 		if ((pptr->iport == NULL) ||
1205 		    (pptr->iport->ua_state != UA_ACTIVE)) {
1206 			tgt = pptr->target;
1207 			if (tgt) {
1208 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
1209 				    "%s: Clearing target 0x%p, inactive iport",
1210 				    __func__, (void *) tgt);
1211 				mutex_enter(&tgt->statlock);
1212 				pmcs_clear_xp(pwp, tgt);
1213 				mutex_exit(&tgt->statlock);
1214 			}
1215 		}
1216 
1217 next_phy:
1218 		if (pptr->children) {
1219 			pnext = pptr->children;
1220 			pnext_uplevel[level++] = pptr->sibling;
1221 		} else {
1222 			pnext = pptr->sibling;
1223 			while ((pnext == NULL) && (level > 0)) {
1224 				pnext = pnext_uplevel[--level];
1225 			}
1226 		}
1227 
1228 		pmcs_unlock_phy(pptr);
1229 		pptr = pnext;
1230 	}
1231 
1232 	return (0);
1233 }
1234 
1235 /*
1236  * Register a device (get a device handle for it).
1237  * Called with PHY lock held.
1238  */
1239 int
1240 pmcs_register_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
1241 {
1242 	struct pmcwork *pwrk;
1243 	int result = 0;
1244 	uint32_t *msg;
1245 	uint32_t tmp, status;
1246 	uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
1247 
1248 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1249 	msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1250 
1251 	if (msg == NULL ||
1252 	    (pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr)) == NULL) {
1253 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1254 		result = ENOMEM;
1255 		goto out;
1256 	}
1257 
1258 	pwrk->arg = iomb;
1259 	pwrk->dtype = pptr->dtype;
1260 
1261 	msg[1] = LE_32(pwrk->htag);
1262 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_REGISTER_DEVICE));
1263 	tmp = PMCS_DEVREG_TLR |
1264 	    (pptr->link_rate << PMCS_DEVREG_LINK_RATE_SHIFT);
1265 	if (IS_ROOT_PHY(pptr)) {
1266 		msg[2] = LE_32(pptr->portid |
1267 		    (pptr->phynum << PMCS_PHYID_SHIFT));
1268 	} else {
1269 		msg[2] = LE_32(pptr->portid);
1270 	}
1271 	if (pptr->dtype == SATA) {
1272 		if (IS_ROOT_PHY(pptr)) {
1273 			tmp |= PMCS_DEVREG_TYPE_SATA_DIRECT;
1274 		} else {
1275 			tmp |= PMCS_DEVREG_TYPE_SATA;
1276 		}
1277 	} else {
1278 		tmp |= PMCS_DEVREG_TYPE_SAS;
1279 	}
1280 	msg[3] = LE_32(tmp);
1281 	msg[4] = LE_32(PMCS_DEVREG_IT_NEXUS_TIMEOUT);
1282 	(void) memcpy(&msg[5], pptr->sas_address, 8);
1283 
1284 	CLEAN_MESSAGE(msg, 7);
1285 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
1286 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1287 
1288 	pmcs_unlock_phy(pptr);
1289 	WAIT_FOR(pwrk, 250, result);
1290 	pmcs_lock_phy(pptr);
1291 	pmcs_pwork(pwp, pwrk);
1292 
1293 	if (result) {
1294 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, pmcs_timeo, __func__);
1295 		result = ETIMEDOUT;
1296 		goto out;
1297 	}
1298 	status = LE_32(iomb[2]);
1299 	tmp = LE_32(iomb[3]);
1300 	switch (status) {
1301 	case PMCS_DEVREG_OK:
1302 	case PMCS_DEVREG_DEVICE_ALREADY_REGISTERED:
1303 	case PMCS_DEVREG_PHY_ALREADY_REGISTERED:
1304 		if (pmcs_validate_devid(pwp->root_phys, pptr, tmp) == B_FALSE) {
1305 			result = EEXIST;
1306 			goto out;
1307 		} else if (status != PMCS_DEVREG_OK) {
1308 			if (tmp == 0xffffffff) {	/* F/W bug */
1309 				pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
1310 				    "%s: phy %s already has bogus devid 0x%x",
1311 				    __func__, pptr->path, tmp);
1312 				result = EIO;
1313 				goto out;
1314 			} else {
1315 				pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL,
1316 				    "%s: phy %s already has a device id 0x%x",
1317 				    __func__, pptr->path, tmp);
1318 			}
1319 		}
1320 		break;
1321 	default:
1322 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1323 		    "%s: status 0x%x when trying to register device %s",
1324 		    __func__, status, pptr->path);
1325 		result = EIO;
1326 		goto out;
1327 	}
1328 	pptr->device_id = tmp;
1329 	pptr->valid_device_id = 1;
1330 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "Phy %s/" SAS_ADDR_FMT
1331 	    " registered with device_id 0x%x (portid %d)", pptr->path,
1332 	    SAS_ADDR_PRT(pptr->sas_address), tmp, pptr->portid);
1333 out:
1334 	return (result);
1335 }
1336 
1337 /*
1338  * Deregister a device (remove a device handle).
1339  * Called with PHY locked.
1340  */
1341 void
1342 pmcs_deregister_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
1343 {
1344 	struct pmcwork *pwrk;
1345 	uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
1346 	uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
1347 	int result;
1348 
1349 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
1350 	if (pwrk == NULL) {
1351 		return;
1352 	}
1353 
1354 	pwrk->arg = iomb;
1355 	pwrk->dtype = pptr->dtype;
1356 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1357 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1358 	if (ptr == NULL) {
1359 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
1360 		pmcs_pwork(pwp, pwrk);
1361 		return;
1362 	}
1363 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
1364 	    PMCIN_DEREGISTER_DEVICE_HANDLE));
1365 	msg[1] = LE_32(pwrk->htag);
1366 	msg[2] = LE_32(pptr->device_id);
1367 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
1368 	COPY_MESSAGE(ptr, msg, 3);
1369 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
1370 
1371 	pmcs_unlock_phy(pptr);
1372 	WAIT_FOR(pwrk, 250, result);
1373 	pmcs_pwork(pwp, pwrk);
1374 	pmcs_lock_phy(pptr);
1375 
1376 	if (result) {
1377 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, pmcs_timeo, __func__);
1378 		return;
1379 	}
1380 	status = LE_32(iomb[2]);
1381 	if (status != PMCOUT_STATUS_OK) {
1382 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1383 		    "%s: status 0x%x when trying to deregister device %s",
1384 		    __func__, status, pptr->path);
1385 	} else {
1386 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1387 		    "%s: device %s deregistered", __func__, pptr->path);
1388 		pptr->valid_device_id = 0;
1389 		pptr->device_id = PMCS_INVALID_DEVICE_ID;
1390 		pptr->configured = 0;
1391 		pptr->deregister_wait = 0;
1392 	}
1393 }
1394 
1395 /*
1396  * Deregister all registered devices.
1397  */
1398 void
1399 pmcs_deregister_devices(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
1400 {
1401 	/*
1402 	 * Start at the maximum level and walk back to level 0.  This only
1403 	 * gets done during detach after all threads and timers have been
1404 	 * destroyed, so there's no need to hold the softstate or PHY lock.
1405 	 */
1406 	while (phyp) {
1407 		if (phyp->children) {
1408 			pmcs_deregister_devices(pwp, phyp->children);
1409 		}
1410 		if (phyp->valid_device_id) {
1411 			pmcs_deregister_device(pwp, phyp);
1412 		}
1413 		phyp = phyp->sibling;
1414 	}
1415 }
1416 
1417 /*
1418  * Perform a 'soft' reset on the PMC chip
1419  */
1420 int
1421 pmcs_soft_reset(pmcs_hw_t *pwp, boolean_t no_restart)
1422 {
1423 	uint32_t s2, sfrbits, gsm, rapchk, wapchk, wdpchk, spc, tsmode;
1424 	pmcs_phy_t *pptr;
1425 	char *msg = NULL;
1426 	int i;
1427 
1428 	/*
1429 	 * Disable interrupts
1430 	 */
1431 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
1432 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
1433 
1434 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "%s", __func__);
1435 
1436 	if (pwp->locks_initted) {
1437 		mutex_enter(&pwp->lock);
1438 	}
1439 	pwp->blocked = 1;
1440 
1441 	/*
1442 	 * Clear our softstate copies of the MSGU and IOP heartbeats.
1443 	 */
1444 	pwp->last_msgu_tick = pwp->last_iop_tick = 0;
1445 
1446 	/*
1447 	 * Step 1
1448 	 */
1449 	s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2);
1450 	if ((s2 & PMCS_MSGU_HOST_SOFT_RESET_READY) == 0) {
1451 		pmcs_wr_gsm_reg(pwp, RB6_ACCESS, RB6_NMI_SIGNATURE);
1452 		pmcs_wr_gsm_reg(pwp, RB6_ACCESS, RB6_NMI_SIGNATURE);
1453 		for (i = 0; i < 100; i++) {
1454 			s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
1455 			    PMCS_MSGU_HOST_SOFT_RESET_READY;
1456 			if (s2) {
1457 				break;
1458 			}
1459 			drv_usecwait(10000);
1460 		}
1461 		s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
1462 		    PMCS_MSGU_HOST_SOFT_RESET_READY;
1463 		if (s2 == 0) {
1464 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1465 			    "%s: PMCS_MSGU_HOST_SOFT_RESET_READY never came "
1466 			    "ready", __func__);
1467 			pmcs_register_dump(pwp);
1468 			if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
1469 			    PMCS_MSGU_CPU_SOFT_RESET_READY) == 0 ||
1470 			    (pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
1471 			    PMCS_MSGU_CPU_SOFT_RESET_READY) == 0) {
1472 				pwp->state = STATE_DEAD;
1473 				pwp->blocked = 0;
1474 				if (pwp->locks_initted) {
1475 					mutex_exit(&pwp->lock);
1476 				}
1477 				return (-1);
1478 			}
1479 		}
1480 	}
1481 
1482 	/*
1483 	 * Step 2
1484 	 */
1485 	pmcs_wr_gsm_reg(pwp, NMI_EN_VPE0_IOP, 0);
1486 	drv_usecwait(10);
1487 	pmcs_wr_gsm_reg(pwp, NMI_EN_VPE0_AAP1, 0);
1488 	drv_usecwait(10);
1489 	pmcs_wr_topunit(pwp, PMCS_EVENT_INT_ENABLE, 0);
1490 	drv_usecwait(10);
1491 	pmcs_wr_topunit(pwp, PMCS_EVENT_INT_STAT,
1492 	    pmcs_rd_topunit(pwp, PMCS_EVENT_INT_STAT));
1493 	drv_usecwait(10);
1494 	pmcs_wr_topunit(pwp, PMCS_ERROR_INT_ENABLE, 0);
1495 	drv_usecwait(10);
1496 	pmcs_wr_topunit(pwp, PMCS_ERROR_INT_STAT,
1497 	    pmcs_rd_topunit(pwp, PMCS_ERROR_INT_STAT));
1498 	drv_usecwait(10);
1499 
1500 	sfrbits = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
1501 	    PMCS_MSGU_AAP_SFR_PROGRESS;
1502 	sfrbits ^= PMCS_MSGU_AAP_SFR_PROGRESS;
1503 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "PMCS_MSGU_HOST_SCRATCH0 "
1504 	    "%08x -> %08x", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0),
1505 	    HST_SFT_RESET_SIG);
1506 	pmcs_wr_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0, HST_SFT_RESET_SIG);
1507 
1508 	/*
1509 	 * Step 3
1510 	 */
1511 	gsm = pmcs_rd_gsm_reg(pwp, 0, GSM_CFG_AND_RESET);
1512 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "GSM %08x -> %08x", gsm,
1513 	    gsm & ~PMCS_SOFT_RESET_BITS);
1514 	pmcs_wr_gsm_reg(pwp, GSM_CFG_AND_RESET, gsm & ~PMCS_SOFT_RESET_BITS);
1515 
1516 	/*
1517 	 * Step 4
1518 	 */
1519 	rapchk = pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_CHK_EN);
1520 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "READ_ADR_PARITY_CHK_EN "
1521 	    "%08x -> %08x", rapchk, 0);
1522 	pmcs_wr_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN, 0);
1523 	wapchk = pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_CHK_EN);
1524 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_ADR_PARITY_CHK_EN "
1525 	    "%08x -> %08x", wapchk, 0);
1526 	pmcs_wr_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN, 0);
1527 	wdpchk = pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_CHK_EN);
1528 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_DATA_PARITY_CHK_EN "
1529 	    "%08x -> %08x", wdpchk, 0);
1530 	pmcs_wr_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN, 0);
1531 
1532 	/*
1533 	 * Step 5
1534 	 */
1535 	drv_usecwait(100);
1536 
1537 	/*
1538 	 * Step 5.5 (Temporary workaround for 1.07.xx Beta)
1539 	 */
1540 	tsmode = pmcs_rd_gsm_reg(pwp, 0, PMCS_GPIO_TRISTATE_MODE_ADDR);
1541 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "GPIO TSMODE %08x -> %08x",
1542 	    tsmode, tsmode & ~(PMCS_GPIO_TSMODE_BIT0|PMCS_GPIO_TSMODE_BIT1));
1543 	pmcs_wr_gsm_reg(pwp, PMCS_GPIO_TRISTATE_MODE_ADDR,
1544 	    tsmode & ~(PMCS_GPIO_TSMODE_BIT0|PMCS_GPIO_TSMODE_BIT1));
1545 	drv_usecwait(10);
1546 
1547 	/*
1548 	 * Step 6
1549 	 */
1550 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1551 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1552 	    spc, spc & ~(PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1553 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET,
1554 	    spc & ~(PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1555 	drv_usecwait(10);
1556 
1557 	/*
1558 	 * Step 7
1559 	 */
1560 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1561 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1562 	    spc, spc & ~(BDMA_CORE_RSTB|OSSP_RSTB));
1563 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET, spc & ~(BDMA_CORE_RSTB|OSSP_RSTB));
1564 
1565 	/*
1566 	 * Step 8
1567 	 */
1568 	drv_usecwait(100);
1569 
1570 	/*
1571 	 * Step 9
1572 	 */
1573 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1574 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1575 	    spc, spc | (BDMA_CORE_RSTB|OSSP_RSTB));
1576 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET, spc | (BDMA_CORE_RSTB|OSSP_RSTB));
1577 
1578 	/*
1579 	 * Step 10
1580 	 */
1581 	drv_usecwait(100);
1582 
1583 	/*
1584 	 * Step 11
1585 	 */
1586 	gsm = pmcs_rd_gsm_reg(pwp, 0, GSM_CFG_AND_RESET);
1587 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "GSM %08x -> %08x", gsm,
1588 	    gsm | PMCS_SOFT_RESET_BITS);
1589 	pmcs_wr_gsm_reg(pwp, GSM_CFG_AND_RESET, gsm | PMCS_SOFT_RESET_BITS);
1590 	drv_usecwait(10);
1591 
1592 	/*
1593 	 * Step 12
1594 	 */
1595 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "READ_ADR_PARITY_CHK_EN "
1596 	    "%08x -> %08x", pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_CHK_EN),
1597 	    rapchk);
1598 	pmcs_wr_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN, rapchk);
1599 	drv_usecwait(10);
1600 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_ADR_PARITY_CHK_EN "
1601 	    "%08x -> %08x", pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_CHK_EN),
1602 	    wapchk);
1603 	pmcs_wr_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN, wapchk);
1604 	drv_usecwait(10);
1605 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "WRITE_DATA_PARITY_CHK_EN "
1606 	    "%08x -> %08x", pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_CHK_EN),
1607 	    wapchk);
1608 	pmcs_wr_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN, wdpchk);
1609 	drv_usecwait(10);
1610 
1611 	/*
1612 	 * Step 13
1613 	 */
1614 	spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
1615 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "SPC_RESET %08x -> %08x",
1616 	    spc, spc | (PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1617 	pmcs_wr_topunit(pwp, PMCS_SPC_RESET,
1618 	    spc | (PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
1619 
1620 	/*
1621 	 * Step 14
1622 	 */
1623 	drv_usecwait(100);
1624 
1625 	/*
1626 	 * Step 15
1627 	 */
1628 	for (spc = 0, i = 0; i < 1000; i++) {
1629 		drv_usecwait(1000);
1630 		spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
1631 		if ((spc & PMCS_MSGU_AAP_SFR_PROGRESS) == sfrbits) {
1632 			break;
1633 		}
1634 	}
1635 
1636 	if ((spc & PMCS_MSGU_AAP_SFR_PROGRESS) != sfrbits) {
1637 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1638 		    "SFR didn't toggle (sfr 0x%x)", spc);
1639 		pwp->state = STATE_DEAD;
1640 		pwp->blocked = 0;
1641 		if (pwp->locks_initted) {
1642 			mutex_exit(&pwp->lock);
1643 		}
1644 		return (-1);
1645 	}
1646 
1647 	/*
1648 	 * Step 16
1649 	 */
1650 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
1651 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
1652 
1653 	/*
1654 	 * Wait for up to 5 seconds for AAP state to come either ready or error.
1655 	 */
1656 	for (i = 0; i < 50; i++) {
1657 		spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
1658 		    PMCS_MSGU_AAP_STATE_MASK;
1659 		if (spc == PMCS_MSGU_AAP_STATE_ERROR ||
1660 		    spc == PMCS_MSGU_AAP_STATE_READY) {
1661 			break;
1662 		}
1663 		drv_usecwait(100000);
1664 	}
1665 	spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
1666 	if ((spc & PMCS_MSGU_AAP_STATE_MASK) != PMCS_MSGU_AAP_STATE_READY) {
1667 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1668 		    "soft reset failed (state 0x%x)", spc);
1669 		pwp->state = STATE_DEAD;
1670 		pwp->blocked = 0;
1671 		if (pwp->locks_initted) {
1672 			mutex_exit(&pwp->lock);
1673 		}
1674 		return (-1);
1675 	}
1676 
1677 	/* Clear the firmware log */
1678 	if (pwp->fwlogp) {
1679 		bzero(pwp->fwlogp, PMCS_FWLOG_SIZE);
1680 	}
1681 
1682 	/* Reset our queue indices and entries */
1683 	bzero(pwp->shadow_iqpi, sizeof (pwp->shadow_iqpi));
1684 	bzero(pwp->last_iqci, sizeof (pwp->last_iqci));
1685 	bzero(pwp->last_htag, sizeof (pwp->last_htag));
1686 	for (i = 0; i < PMCS_NIQ; i++) {
1687 		if (pwp->iqp[i]) {
1688 			bzero(pwp->iqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
1689 			pmcs_wr_iqpi(pwp, i, 0);
1690 			pmcs_wr_iqci(pwp, i, 0);
1691 		}
1692 	}
1693 	for (i = 0; i < PMCS_NOQ; i++) {
1694 		if (pwp->oqp[i]) {
1695 			bzero(pwp->oqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
1696 			pmcs_wr_oqpi(pwp, i, 0);
1697 			pmcs_wr_oqci(pwp, i, 0);
1698 		}
1699 
1700 	}
1701 
1702 	if (pwp->state == STATE_DEAD || pwp->state == STATE_UNPROBING ||
1703 	    pwp->state == STATE_PROBING || pwp->locks_initted == 0) {
1704 		pwp->blocked = 0;
1705 		if (pwp->locks_initted) {
1706 			mutex_exit(&pwp->lock);
1707 		}
1708 		return (0);
1709 	}
1710 
1711 	/*
1712 	 * Return at this point if we dont need to startup.
1713 	 */
1714 	if (no_restart) {
1715 		return (0);
1716 	}
1717 
1718 	ASSERT(pwp->locks_initted != 0);
1719 
1720 	/*
1721 	 * Flush the target queues and clear each target's PHY
1722 	 */
1723 	if (pwp->targets) {
1724 		for (i = 0; i < pwp->max_dev; i++) {
1725 			pmcs_xscsi_t *xp = pwp->targets[i];
1726 
1727 			if (xp == NULL) {
1728 				continue;
1729 			}
1730 
1731 			mutex_enter(&xp->statlock);
1732 			pmcs_flush_target_queues(pwp, xp, PMCS_TGT_ALL_QUEUES);
1733 			xp->phy = NULL;
1734 			mutex_exit(&xp->statlock);
1735 		}
1736 	}
1737 
1738 	/*
1739 	 * Zero out the ports list, free non root phys, clear root phys
1740 	 */
1741 	bzero(pwp->ports, sizeof (pwp->ports));
1742 	pmcs_free_all_phys(pwp, pwp->root_phys);
1743 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
1744 		pmcs_lock_phy(pptr);
1745 		pmcs_clear_phy(pwp, pptr);
1746 		pptr->target = NULL;
1747 		pmcs_unlock_phy(pptr);
1748 	}
1749 
1750 	/*
1751 	 * Restore Interrupt Mask
1752 	 */
1753 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, pwp->intr_mask);
1754 	pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
1755 
1756 	pwp->mpi_table_setup = 0;
1757 	mutex_exit(&pwp->lock);
1758 
1759 	/*
1760 	 * Set up MPI again.
1761 	 */
1762 	if (pmcs_setup(pwp)) {
1763 		msg = "unable to setup MPI tables again";
1764 		goto fail_restart;
1765 	}
1766 	pmcs_report_fwversion(pwp);
1767 
1768 	/*
1769 	 * Restart MPI
1770 	 */
1771 	if (pmcs_start_mpi(pwp)) {
1772 		msg = "unable to restart MPI again";
1773 		goto fail_restart;
1774 	}
1775 
1776 	mutex_enter(&pwp->lock);
1777 	SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
1778 	mutex_exit(&pwp->lock);
1779 
1780 	/*
1781 	 * Run any completions
1782 	 */
1783 	PMCS_CQ_RUN(pwp);
1784 
1785 	/*
1786 	 * Delay
1787 	 */
1788 	drv_usecwait(1000000);
1789 	return (0);
1790 
1791 fail_restart:
1792 	mutex_enter(&pwp->lock);
1793 	pwp->state = STATE_DEAD;
1794 	mutex_exit(&pwp->lock);
1795 	pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
1796 	    "%s: Failed: %s", __func__, msg);
1797 	return (-1);
1798 }
1799 
1800 
1801 /*
1802  * Perform a 'hot' reset, which will soft reset the chip and
1803  * restore the state back to pre-reset context. Called with pwp
1804  * lock held.
1805  */
1806 int
1807 pmcs_hot_reset(pmcs_hw_t *pwp)
1808 {
1809 	pmcs_iport_t	*iport;
1810 
1811 	ASSERT(mutex_owned(&pwp->lock));
1812 	pwp->state = STATE_IN_RESET;
1813 
1814 	/*
1815 	 * For any iports on this HBA, report empty target sets and
1816 	 * then tear them down.
1817 	 */
1818 	rw_enter(&pwp->iports_lock, RW_READER);
1819 	for (iport = list_head(&pwp->iports); iport != NULL;
1820 	    iport = list_next(&pwp->iports, iport)) {
1821 		mutex_enter(&iport->lock);
1822 		(void) scsi_hba_tgtmap_set_begin(iport->iss_tgtmap);
1823 		(void) scsi_hba_tgtmap_set_end(iport->iss_tgtmap, 0);
1824 		pmcs_iport_teardown_phys(iport);
1825 		mutex_exit(&iport->lock);
1826 	}
1827 	rw_exit(&pwp->iports_lock);
1828 
1829 	/* Grab a register dump, in the event that reset fails */
1830 	pmcs_register_dump_int(pwp);
1831 	mutex_exit(&pwp->lock);
1832 
1833 	/* Issue soft reset and clean up related softstate */
1834 	if (pmcs_soft_reset(pwp, B_FALSE)) {
1835 		/*
1836 		 * Disable interrupts, in case we got far enough along to
1837 		 * enable them, then fire off ereport and service impact.
1838 		 */
1839 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1840 		    "%s: failed soft reset", __func__);
1841 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
1842 		pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
1843 		pmcs_fm_ereport(pwp, DDI_FM_DEVICE_NO_RESPONSE);
1844 		ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
1845 		mutex_enter(&pwp->lock);
1846 		pwp->state = STATE_DEAD;
1847 		return (DDI_FAILURE);
1848 	}
1849 
1850 	mutex_enter(&pwp->lock);
1851 	pwp->state = STATE_RUNNING;
1852 	mutex_exit(&pwp->lock);
1853 
1854 	/*
1855 	 * Finally, restart the phys, which will bring the iports back
1856 	 * up and eventually result in discovery running.
1857 	 */
1858 	if (pmcs_start_phys(pwp)) {
1859 		/* We should be up and running now, so retry */
1860 		if (pmcs_start_phys(pwp)) {
1861 			/* Apparently unable to restart PHYs, fail */
1862 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1863 			    "%s: failed to restart PHYs after soft reset",
1864 			    __func__);
1865 			mutex_enter(&pwp->lock);
1866 			return (DDI_FAILURE);
1867 		}
1868 	}
1869 
1870 	mutex_enter(&pwp->lock);
1871 	return (DDI_SUCCESS);
1872 }
1873 
1874 /*
1875  * Reset a device or a logical unit.
1876  */
1877 int
1878 pmcs_reset_dev(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint64_t lun)
1879 {
1880 	int rval = 0;
1881 
1882 	if (pptr == NULL) {
1883 		return (ENXIO);
1884 	}
1885 
1886 	pmcs_lock_phy(pptr);
1887 	if (pptr->dtype == SAS) {
1888 		/*
1889 		 * Some devices do not support SAS_I_T_NEXUS_RESET as
1890 		 * it is not a mandatory (in SAM4) task management
1891 		 * function, while LOGIC_UNIT_RESET is mandatory.
1892 		 *
1893 		 * The problem here is that we need to iterate over
1894 		 * all known LUNs to emulate the semantics of
1895 		 * "RESET_TARGET".
1896 		 *
1897 		 * XXX: FIX ME
1898 		 */
1899 		if (lun == (uint64_t)-1) {
1900 			lun = 0;
1901 		}
1902 		rval = pmcs_ssp_tmf(pwp, pptr, SAS_LOGICAL_UNIT_RESET, 0, lun,
1903 		    NULL);
1904 	} else if (pptr->dtype == SATA) {
1905 		if (lun != 0ull) {
1906 			pmcs_unlock_phy(pptr);
1907 			return (EINVAL);
1908 		}
1909 		rval = pmcs_reset_phy(pwp, pptr, PMCS_PHYOP_LINK_RESET);
1910 	} else {
1911 		pmcs_unlock_phy(pptr);
1912 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
1913 		    "%s: cannot reset a SMP device yet (%s)",
1914 		    __func__, pptr->path);
1915 		return (EINVAL);
1916 	}
1917 
1918 	/*
1919 	 * Now harvest any commands killed by this action
1920 	 * by issuing an ABORT for all commands on this device.
1921 	 *
1922 	 * We do this even if the the tmf or reset fails (in case there
1923 	 * are any dead commands around to be harvested *anyway*).
1924 	 * We don't have to await for the abort to complete.
1925 	 */
1926 	if (pmcs_abort(pwp, pptr, 0, 1, 0)) {
1927 		pptr->abort_pending = 1;
1928 		SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
1929 	}
1930 
1931 	pmcs_unlock_phy(pptr);
1932 	return (rval);
1933 }
1934 
1935 /*
1936  * Called with PHY locked.
1937  */
1938 static int
1939 pmcs_get_device_handle(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
1940 {
1941 	if (pptr->valid_device_id == 0) {
1942 		int result = pmcs_register_device(pwp, pptr);
1943 
1944 		/*
1945 		 * If we changed while registering, punt
1946 		 */
1947 		if (pptr->changed) {
1948 			RESTART_DISCOVERY(pwp);
1949 			return (-1);
1950 		}
1951 
1952 		/*
1953 		 * If we had a failure to register, check against errors.
1954 		 * An ENOMEM error means we just retry (temp resource shortage).
1955 		 */
1956 		if (result == ENOMEM) {
1957 			PHY_CHANGED(pwp, pptr);
1958 			RESTART_DISCOVERY(pwp);
1959 			return (-1);
1960 		}
1961 
1962 		/*
1963 		 * An ETIMEDOUT error means we retry (if our counter isn't
1964 		 * exhausted)
1965 		 */
1966 		if (result == ETIMEDOUT) {
1967 			if (ddi_get_lbolt() < pptr->config_stop) {
1968 				PHY_CHANGED(pwp, pptr);
1969 				RESTART_DISCOVERY(pwp);
1970 			} else {
1971 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
1972 				    "%s: Retries exhausted for %s, killing",
1973 				    __func__, pptr->path);
1974 				pptr->config_stop = 0;
1975 				pmcs_kill_changed(pwp, pptr, 0);
1976 			}
1977 			return (-1);
1978 		}
1979 		/*
1980 		 * Other errors or no valid device id is fatal, but don't
1981 		 * preclude a future action.
1982 		 */
1983 		if (result || pptr->valid_device_id == 0) {
1984 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
1985 			    "%s: %s could not be registered", __func__,
1986 			    pptr->path);
1987 			return (-1);
1988 		}
1989 	}
1990 	return (0);
1991 }
1992 
1993 int
1994 pmcs_iport_tgtmap_create(pmcs_iport_t *iport)
1995 {
1996 	ASSERT(iport);
1997 	if (iport == NULL)
1998 		return (B_FALSE);
1999 
2000 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s", __func__);
2001 
2002 	/* create target map */
2003 	if (scsi_hba_tgtmap_create(iport->dip, SCSI_TM_FULLSET, tgtmap_usec,
2004 	    (void *)iport, pmcs_tgtmap_activate_cb, pmcs_tgtmap_deactivate_cb,
2005 	    &iport->iss_tgtmap) != DDI_SUCCESS) {
2006 		pmcs_prt(iport->pwp, PMCS_PRT_DEBUG, NULL, NULL,
2007 		    "%s: failed to create tgtmap", __func__);
2008 		return (B_FALSE);
2009 	}
2010 	return (B_TRUE);
2011 }
2012 
2013 int
2014 pmcs_iport_tgtmap_destroy(pmcs_iport_t *iport)
2015 {
2016 	ASSERT(iport && iport->iss_tgtmap);
2017 	if ((iport == NULL) || (iport->iss_tgtmap == NULL))
2018 		return (B_FALSE);
2019 
2020 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s", __func__);
2021 
2022 	/* destroy target map */
2023 	scsi_hba_tgtmap_destroy(iport->iss_tgtmap);
2024 	return (B_TRUE);
2025 }
2026 
2027 /*
2028  * Remove all phys from an iport's phymap and empty it's phylist.
2029  * Called when a port has been reset by the host (see pmcs_intr.c)
2030  * or prior to issuing a soft reset if we detect a stall on the chip
2031  * (see pmcs_attach.c).
2032  */
2033 void
2034 pmcs_iport_teardown_phys(pmcs_iport_t *iport)
2035 {
2036 	pmcs_hw_t		*pwp;
2037 	sas_phymap_phys_t	*phys;
2038 	int			phynum;
2039 
2040 	ASSERT(iport);
2041 	ASSERT(mutex_owned(&iport->lock));
2042 	pwp = iport->pwp;
2043 	ASSERT(pwp);
2044 
2045 	/*
2046 	 * Remove all phys from the iport handle's phy list, unset its
2047 	 * primary phy and update its state.
2048 	 */
2049 	pmcs_remove_phy_from_iport(iport, NULL);
2050 	iport->pptr = NULL;
2051 	iport->ua_state = UA_PEND_DEACTIVATE;
2052 
2053 	/* Remove all phys from the phymap */
2054 	phys = sas_phymap_ua2phys(pwp->hss_phymap, iport->ua);
2055 	if (phys) {
2056 		while ((phynum = sas_phymap_phys_next(phys)) != -1) {
2057 			(void) sas_phymap_phy_rem(pwp->hss_phymap, phynum);
2058 		}
2059 		sas_phymap_phys_free(phys);
2060 	}
2061 }
2062 
2063 /*
2064  * Query the phymap and populate the iport handle passed in.
2065  * Called with iport lock held.
2066  */
2067 int
2068 pmcs_iport_configure_phys(pmcs_iport_t *iport)
2069 {
2070 	pmcs_hw_t		*pwp;
2071 	pmcs_phy_t		*pptr;
2072 	sas_phymap_phys_t	*phys;
2073 	int			phynum;
2074 	int			inst;
2075 
2076 	ASSERT(iport);
2077 	ASSERT(mutex_owned(&iport->lock));
2078 	pwp = iport->pwp;
2079 	ASSERT(pwp);
2080 	inst = ddi_get_instance(iport->dip);
2081 
2082 	mutex_enter(&pwp->lock);
2083 	ASSERT(pwp->root_phys != NULL);
2084 
2085 	/*
2086 	 * Query the phymap regarding the phys in this iport and populate
2087 	 * the iport's phys list. Hereafter this list is maintained via
2088 	 * port up and down events in pmcs_intr.c
2089 	 */
2090 	ASSERT(list_is_empty(&iport->phys));
2091 	phys = sas_phymap_ua2phys(pwp->hss_phymap, iport->ua);
2092 	ASSERT(phys != NULL);
2093 	while ((phynum = sas_phymap_phys_next(phys)) != -1) {
2094 		/* Grab the phy pointer from root_phys */
2095 		pptr = pwp->root_phys + phynum;
2096 		ASSERT(pptr);
2097 		pmcs_lock_phy(pptr);
2098 		ASSERT(pptr->phynum == phynum);
2099 
2100 		/*
2101 		 * Set a back pointer in the phy to this iport.
2102 		 */
2103 		pptr->iport = iport;
2104 
2105 		/*
2106 		 * If this phy is the primary, set a pointer to it on our
2107 		 * iport handle, and set our portid from it.
2108 		 */
2109 		if (!pptr->subsidiary) {
2110 			iport->pptr = pptr;
2111 			iport->portid = pptr->portid;
2112 		}
2113 
2114 		/*
2115 		 * Finally, insert the phy into our list
2116 		 */
2117 		pmcs_unlock_phy(pptr);
2118 		pmcs_add_phy_to_iport(iport, pptr);
2119 
2120 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "%s: found "
2121 		    "phy %d [0x%p] on iport%d, refcnt(%d)", __func__, phynum,
2122 		    (void *)pptr, inst, iport->refcnt);
2123 	}
2124 	mutex_exit(&pwp->lock);
2125 	sas_phymap_phys_free(phys);
2126 	RESTART_DISCOVERY(pwp);
2127 	return (DDI_SUCCESS);
2128 }
2129 
2130 /*
2131  * Return the iport that ua is associated with, or NULL.  If an iport is
2132  * returned, it will be held and the caller must release the hold.
2133  */
2134 static pmcs_iport_t *
2135 pmcs_get_iport_by_ua(pmcs_hw_t *pwp, char *ua)
2136 {
2137 	pmcs_iport_t	*iport = NULL;
2138 
2139 	rw_enter(&pwp->iports_lock, RW_READER);
2140 	for (iport = list_head(&pwp->iports);
2141 	    iport != NULL;
2142 	    iport = list_next(&pwp->iports, iport)) {
2143 		mutex_enter(&iport->lock);
2144 		if (strcmp(iport->ua, ua) == 0) {
2145 			mutex_exit(&iport->lock);
2146 			mutex_enter(&iport->refcnt_lock);
2147 			iport->refcnt++;
2148 			mutex_exit(&iport->refcnt_lock);
2149 			break;
2150 		}
2151 		mutex_exit(&iport->lock);
2152 	}
2153 	rw_exit(&pwp->iports_lock);
2154 
2155 	return (iport);
2156 }
2157 
2158 /*
2159  * Return the iport that pptr is associated with, or NULL.
2160  * If an iport is returned, there is a hold that the caller must release.
2161  */
2162 pmcs_iport_t *
2163 pmcs_get_iport_by_wwn(pmcs_hw_t *pwp, uint64_t wwn)
2164 {
2165 	pmcs_iport_t	*iport = NULL;
2166 	char		*ua;
2167 
2168 	ua = sas_phymap_lookup_ua(pwp->hss_phymap, pwp->sas_wwns[0], wwn);
2169 	if (ua) {
2170 		iport = pmcs_get_iport_by_ua(pwp, ua);
2171 		if (iport) {
2172 			mutex_enter(&iport->lock);
2173 			pmcs_iport_active(iport);
2174 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "%s: "
2175 			    "found iport [0x%p] on ua (%s), refcnt (%d)",
2176 			    __func__, (void *)iport, ua, iport->refcnt);
2177 			mutex_exit(&iport->lock);
2178 		}
2179 	}
2180 
2181 	return (iport);
2182 }
2183 
2184 /*
2185  * Promote the next phy on this port to primary, and return it.
2186  * Called when the primary PHY on a port is going down, but the port
2187  * remains up (see pmcs_intr.c).
2188  */
2189 pmcs_phy_t *
2190 pmcs_promote_next_phy(pmcs_phy_t *prev_primary)
2191 {
2192 	pmcs_hw_t	*pwp;
2193 	pmcs_iport_t	*iport;
2194 	pmcs_phy_t	*pptr, *child;
2195 	int		portid;
2196 
2197 	pmcs_lock_phy(prev_primary);
2198 	portid = prev_primary->portid;
2199 	iport  = prev_primary->iport;
2200 	pwp    = prev_primary->pwp;
2201 
2202 	/* Use the first available phy in this port */
2203 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
2204 		if ((pptr->portid == portid) && (pptr != prev_primary)) {
2205 			mutex_enter(&pptr->phy_lock);
2206 			break;
2207 		}
2208 	}
2209 
2210 	if (pptr == NULL) {
2211 		pmcs_unlock_phy(prev_primary);
2212 		return (NULL);
2213 	}
2214 
2215 	if (iport) {
2216 		mutex_enter(&iport->lock);
2217 		iport->pptr = pptr;
2218 		mutex_exit(&iport->lock);
2219 	}
2220 
2221 	/* Update the phy handle with the data from the previous primary */
2222 	pptr->children		= prev_primary->children;
2223 	child = pptr->children;
2224 	while (child) {
2225 		child->parent = pptr;
2226 		child = child->sibling;
2227 	}
2228 	pptr->ncphy		= prev_primary->ncphy;
2229 	pptr->width		= prev_primary->width;
2230 	pptr->dtype		= prev_primary->dtype;
2231 	pptr->pend_dtype	= prev_primary->pend_dtype;
2232 	pptr->tolerates_sas2	= prev_primary->tolerates_sas2;
2233 	pptr->atdt		= prev_primary->atdt;
2234 	pptr->portid		= prev_primary->portid;
2235 	pptr->link_rate		= prev_primary->link_rate;
2236 	pptr->configured	= prev_primary->configured;
2237 	pptr->iport		= prev_primary->iport;
2238 	pptr->target		= prev_primary->target;
2239 	if (pptr->target) {
2240 		pptr->target->phy = pptr;
2241 	}
2242 
2243 	/* Update the phy mask properties for the affected PHYs */
2244 	/* Clear the current values... */
2245 	pmcs_update_phy_pm_props(pptr, pptr->att_port_pm_tmp,
2246 	    pptr->tgt_port_pm_tmp, B_FALSE);
2247 	/* ...replace with the values from prev_primary... */
2248 	pmcs_update_phy_pm_props(pptr, prev_primary->att_port_pm_tmp,
2249 	    prev_primary->tgt_port_pm_tmp, B_TRUE);
2250 	/* ...then clear prev_primary's PHY values from the new primary */
2251 	pmcs_update_phy_pm_props(pptr, prev_primary->att_port_pm,
2252 	    prev_primary->tgt_port_pm, B_FALSE);
2253 	/* Clear the prev_primary's values */
2254 	pmcs_update_phy_pm_props(prev_primary, prev_primary->att_port_pm_tmp,
2255 	    prev_primary->tgt_port_pm_tmp, B_FALSE);
2256 
2257 	pptr->subsidiary = 0;
2258 
2259 	prev_primary->subsidiary = 1;
2260 	prev_primary->children = NULL;
2261 	prev_primary->target = NULL;
2262 	pptr->device_id = prev_primary->device_id;
2263 	pptr->valid_device_id = 1;
2264 	pmcs_unlock_phy(prev_primary);
2265 
2266 	/*
2267 	 * We call pmcs_unlock_phy() on pptr because it now contains the
2268 	 * list of children.
2269 	 */
2270 	pmcs_unlock_phy(pptr);
2271 
2272 	return (pptr);
2273 }
2274 
2275 void
2276 pmcs_rele_iport(pmcs_iport_t *iport)
2277 {
2278 	/*
2279 	 * Release a refcnt on this iport. If this is the last reference,
2280 	 * signal the potential waiter in pmcs_iport_unattach().
2281 	 */
2282 	ASSERT(iport->refcnt > 0);
2283 	mutex_enter(&iport->refcnt_lock);
2284 	iport->refcnt--;
2285 	mutex_exit(&iport->refcnt_lock);
2286 	if (iport->refcnt == 0) {
2287 		cv_signal(&iport->refcnt_cv);
2288 	}
2289 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "%s: iport "
2290 	    "[0x%p] refcnt (%d)", __func__, (void *)iport, iport->refcnt);
2291 }
2292 
2293 void
2294 pmcs_phymap_activate(void *arg, char *ua, void **privp)
2295 {
2296 	_NOTE(ARGUNUSED(privp));
2297 	pmcs_hw_t	*pwp = arg;
2298 	pmcs_iport_t	*iport = NULL;
2299 
2300 	mutex_enter(&pwp->lock);
2301 	if ((pwp->state == STATE_UNPROBING) || (pwp->state == STATE_DEAD)) {
2302 		mutex_exit(&pwp->lock);
2303 		return;
2304 	}
2305 	pwp->phymap_active++;
2306 	mutex_exit(&pwp->lock);
2307 
2308 	if (scsi_hba_iportmap_iport_add(pwp->hss_iportmap, ua, NULL) !=
2309 	    DDI_SUCCESS) {
2310 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: failed to "
2311 		    "add iport handle on unit address [%s]", __func__, ua);
2312 	} else {
2313 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: "
2314 		    "phymap_active count (%d), added iport handle on unit "
2315 		    "address [%s]", __func__, pwp->phymap_active, ua);
2316 	}
2317 
2318 	/* Set the HBA softstate as our private data for this unit address */
2319 	*privp = (void *)pwp;
2320 
2321 	/*
2322 	 * We are waiting on attach for this iport node, unless it is still
2323 	 * attached. This can happen if a consumer has an outstanding open
2324 	 * on our iport node, but the port is down.  If this is the case, we
2325 	 * need to configure our iport here for reuse.
2326 	 */
2327 	iport = pmcs_get_iport_by_ua(pwp, ua);
2328 	if (iport) {
2329 		mutex_enter(&iport->lock);
2330 		if (pmcs_iport_configure_phys(iport) != DDI_SUCCESS) {
2331 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "%s: "
2332 			    "failed to configure phys on iport [0x%p] at "
2333 			    "unit address (%s)", __func__, (void *)iport, ua);
2334 		}
2335 		pmcs_iport_active(iport);
2336 		pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
2337 		    &iport->nphy);
2338 		mutex_exit(&iport->lock);
2339 		pmcs_rele_iport(iport);
2340 	}
2341 
2342 }
2343 
2344 void
2345 pmcs_phymap_deactivate(void *arg, char *ua, void *privp)
2346 {
2347 	_NOTE(ARGUNUSED(privp));
2348 	pmcs_hw_t	*pwp = arg;
2349 	pmcs_iport_t	*iport;
2350 
2351 	mutex_enter(&pwp->lock);
2352 	pwp->phymap_active--;
2353 	mutex_exit(&pwp->lock);
2354 
2355 	if (scsi_hba_iportmap_iport_remove(pwp->hss_iportmap, ua) !=
2356 	    DDI_SUCCESS) {
2357 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: failed to "
2358 		    "remove iport handle on unit address [%s]", __func__, ua);
2359 	} else {
2360 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL, "%s: "
2361 		    "phymap_active count (%d), removed iport handle on unit "
2362 		    "address [%s]", __func__, pwp->phymap_active, ua);
2363 	}
2364 
2365 	iport = pmcs_get_iport_by_ua(pwp, ua);
2366 
2367 	if (iport == NULL) {
2368 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "%s: failed "
2369 		    "lookup of iport handle on unit addr (%s)", __func__, ua);
2370 		return;
2371 	}
2372 
2373 	mutex_enter(&iport->lock);
2374 	iport->ua_state = UA_INACTIVE;
2375 	iport->portid = PMCS_IPORT_INVALID_PORT_ID;
2376 	pmcs_remove_phy_from_iport(iport, NULL);
2377 	mutex_exit(&iport->lock);
2378 	pmcs_rele_iport(iport);
2379 }
2380 
2381 /*
2382  * Top-level discovery function
2383  */
2384 void
2385 pmcs_discover(pmcs_hw_t *pwp)
2386 {
2387 	pmcs_phy_t		*pptr;
2388 	pmcs_phy_t		*root_phy;
2389 
2390 	DTRACE_PROBE2(pmcs__discover__entry, ulong_t, pwp->work_flags,
2391 	    boolean_t, pwp->config_changed);
2392 
2393 	mutex_enter(&pwp->lock);
2394 
2395 	if (pwp->state != STATE_RUNNING) {
2396 		mutex_exit(&pwp->lock);
2397 		return;
2398 	}
2399 
2400 	/* Ensure we have at least one phymap active */
2401 	if (pwp->phymap_active == 0) {
2402 		mutex_exit(&pwp->lock);
2403 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2404 		    "%s: phymap inactive, exiting", __func__);
2405 		return;
2406 	}
2407 
2408 	mutex_exit(&pwp->lock);
2409 
2410 	/*
2411 	 * If no iports have attached, but we have PHYs that are up, we
2412 	 * are waiting for iport attach to complete.  Restart discovery.
2413 	 */
2414 	rw_enter(&pwp->iports_lock, RW_READER);
2415 	if (!pwp->iports_attached) {
2416 		rw_exit(&pwp->iports_lock);
2417 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2418 		    "%s: no iports attached, retry discovery", __func__);
2419 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2420 		return;
2421 	}
2422 	rw_exit(&pwp->iports_lock);
2423 
2424 	mutex_enter(&pwp->config_lock);
2425 	if (pwp->configuring) {
2426 		mutex_exit(&pwp->config_lock);
2427 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2428 		    "%s: configuration already in progress", __func__);
2429 		return;
2430 	}
2431 
2432 	if (pmcs_acquire_scratch(pwp, B_FALSE)) {
2433 		mutex_exit(&pwp->config_lock);
2434 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2435 		    "%s: cannot allocate scratch", __func__);
2436 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2437 		return;
2438 	}
2439 
2440 	pwp->configuring = 1;
2441 	pwp->config_changed = B_FALSE;
2442 	mutex_exit(&pwp->config_lock);
2443 
2444 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "Discovery begin");
2445 
2446 	/*
2447 	 * First, tell SCSA that we're beginning set operations.
2448 	 */
2449 	pmcs_begin_observations(pwp);
2450 
2451 	/*
2452 	 * The order of the following traversals is important.
2453 	 *
2454 	 * The first one checks for changed expanders.
2455 	 *
2456 	 * The second one aborts commands for dead devices and deregisters them.
2457 	 *
2458 	 * The third one clears the contents of dead expanders from the tree
2459 	 *
2460 	 * The fourth one clears now dead devices in expanders that remain.
2461 	 */
2462 
2463 	/*
2464 	 * 1. Check expanders marked changed (but not dead) to see if they still
2465 	 * have the same number of phys and the same SAS address. Mark them,
2466 	 * their subsidiary phys (if wide) and their descendents dead if
2467 	 * anything has changed. Check the devices they contain to see if
2468 	 * *they* have changed. If they've changed from type NOTHING we leave
2469 	 * them marked changed to be configured later (picking up a new SAS
2470 	 * address and link rate if possible). Otherwise, any change in type,
2471 	 * SAS address or removal of target role will cause us to mark them
2472 	 * (and their descendents) as dead (and cause any pending commands
2473 	 * and associated devices to be removed).
2474 	 *
2475 	 * NOTE: We don't want to bail on discovery if the config has
2476 	 * changed until *after* we run pmcs_kill_devices.
2477 	 */
2478 	root_phy = pwp->root_phys;
2479 	pmcs_check_expanders(pwp, root_phy);
2480 
2481 	/*
2482 	 * 2. Descend the tree looking for dead devices and kill them
2483 	 * by aborting all active commands and then deregistering them.
2484 	 */
2485 	if (pmcs_kill_devices(pwp, root_phy)) {
2486 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2487 		    "%s: pmcs_kill_devices failed!", __func__);
2488 	}
2489 
2490 	/*
2491 	 * 3. Check for dead expanders and remove their children from the tree.
2492 	 * By the time we get here, the devices and commands for them have
2493 	 * already been terminated and removed.
2494 	 *
2495 	 * We do this independent of the configuration count changing so we can
2496 	 * free any dead device PHYs that were discovered while checking
2497 	 * expanders. We ignore any subsidiary phys as pmcs_clear_expander
2498 	 * will take care of those.
2499 	 *
2500 	 * NOTE: pmcs_clear_expander requires softstate lock
2501 	 */
2502 	mutex_enter(&pwp->lock);
2503 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
2504 		/*
2505 		 * Call pmcs_clear_expander for every root PHY.  It will
2506 		 * recurse and determine which (if any) expanders actually
2507 		 * need to be cleared.
2508 		 */
2509 		pmcs_lock_phy(pptr);
2510 		pmcs_clear_expander(pwp, pptr, 0);
2511 		pmcs_unlock_phy(pptr);
2512 	}
2513 	mutex_exit(&pwp->lock);
2514 
2515 	/*
2516 	 * 4. Check for dead devices and nullify them. By the time we get here,
2517 	 * the devices and commands for them have already been terminated
2518 	 * and removed. This is different from step 2 in that this just nulls
2519 	 * phys that are part of expanders that are still here but used to
2520 	 * be something but are no longer something (e.g., after a pulled
2521 	 * disk drive). Note that dead expanders had their contained phys
2522 	 * removed from the tree- here, the expanders themselves are
2523 	 * nullified (unless they were removed by being contained in another
2524 	 * expander phy).
2525 	 */
2526 	pmcs_clear_phys(pwp, root_phy);
2527 
2528 	/*
2529 	 * 5. Now check for and configure new devices.
2530 	 */
2531 	if (pmcs_configure_new_devices(pwp, root_phy)) {
2532 		goto restart;
2533 	}
2534 
2535 out:
2536 	DTRACE_PROBE2(pmcs__discover__exit, ulong_t, pwp->work_flags,
2537 	    boolean_t, pwp->config_changed);
2538 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, "Discovery end");
2539 
2540 	mutex_enter(&pwp->config_lock);
2541 
2542 	if (pwp->config_changed == B_FALSE) {
2543 		/*
2544 		 * Observation is stable, report what we currently see to
2545 		 * the tgtmaps for delta processing. Start by setting
2546 		 * BEGIN on all tgtmaps.
2547 		 */
2548 		mutex_exit(&pwp->config_lock);
2549 		if (pmcs_report_observations(pwp) == B_FALSE) {
2550 			goto restart;
2551 		}
2552 		mutex_enter(&pwp->config_lock);
2553 	} else {
2554 		/*
2555 		 * If config_changed is TRUE, we need to reschedule
2556 		 * discovery now.
2557 		 */
2558 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2559 		    "%s: Config has changed, will re-run discovery", __func__);
2560 		SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
2561 	}
2562 
2563 	pmcs_release_scratch(pwp);
2564 	if (!pwp->quiesced) {
2565 		pwp->blocked = 0;
2566 	}
2567 	pwp->configuring = 0;
2568 	mutex_exit(&pwp->config_lock);
2569 
2570 #ifdef DEBUG
2571 	pptr = pmcs_find_phy_needing_work(pwp, pwp->root_phys);
2572 	if (pptr != NULL) {
2573 		if (!WORK_IS_SCHEDULED(pwp, PMCS_WORK_DISCOVER)) {
2574 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
2575 			    "PHY %s dead=%d changed=%d configured=%d "
2576 			    "but no work scheduled", pptr->path, pptr->dead,
2577 			    pptr->changed, pptr->configured);
2578 		}
2579 		pmcs_unlock_phy(pptr);
2580 	}
2581 #endif
2582 
2583 	return;
2584 
2585 restart:
2586 	/* Clean up and restart discovery */
2587 	pmcs_release_scratch(pwp);
2588 	pmcs_flush_observations(pwp);
2589 	mutex_enter(&pwp->config_lock);
2590 	pwp->configuring = 0;
2591 	RESTART_DISCOVERY_LOCKED(pwp);
2592 	mutex_exit(&pwp->config_lock);
2593 }
2594 
2595 /*
2596  * Return any PHY that needs to have scheduled work done.  The PHY is returned
2597  * locked.
2598  */
2599 static pmcs_phy_t *
2600 pmcs_find_phy_needing_work(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2601 {
2602 	pmcs_phy_t *cphyp, *pnext;
2603 
2604 	while (pptr) {
2605 		pmcs_lock_phy(pptr);
2606 
2607 		if (pptr->changed || (pptr->dead && pptr->valid_device_id)) {
2608 			return (pptr);
2609 		}
2610 
2611 		pnext = pptr->sibling;
2612 
2613 		if (pptr->children) {
2614 			cphyp = pptr->children;
2615 			pmcs_unlock_phy(pptr);
2616 			cphyp = pmcs_find_phy_needing_work(pwp, cphyp);
2617 			if (cphyp) {
2618 				return (cphyp);
2619 			}
2620 		} else {
2621 			pmcs_unlock_phy(pptr);
2622 		}
2623 
2624 		pptr = pnext;
2625 	}
2626 
2627 	return (NULL);
2628 }
2629 
2630 /*
2631  * We may (or may not) report observations to SCSA.  This is prefaced by
2632  * issuing a set_begin for each iport target map.
2633  */
2634 static void
2635 pmcs_begin_observations(pmcs_hw_t *pwp)
2636 {
2637 	pmcs_iport_t		*iport;
2638 	scsi_hba_tgtmap_t	*tgtmap;
2639 
2640 	rw_enter(&pwp->iports_lock, RW_READER);
2641 	for (iport = list_head(&pwp->iports); iport != NULL;
2642 	    iport = list_next(&pwp->iports, iport)) {
2643 		/*
2644 		 * Unless we have at least one phy up, skip this iport.
2645 		 * Note we don't need to lock the iport for report_skip
2646 		 * since it is only used here.  We are doing the skip so that
2647 		 * the phymap and iportmap stabilization times are honored -
2648 		 * giving us the ability to recover port operation within the
2649 		 * stabilization time without unconfiguring targets using the
2650 		 * port.
2651 		 */
2652 		if (!sas_phymap_uahasphys(pwp->hss_phymap, iport->ua)) {
2653 			iport->report_skip = 1;
2654 			continue;		/* skip set_begin */
2655 		}
2656 		iport->report_skip = 0;
2657 
2658 		tgtmap = iport->iss_tgtmap;
2659 		ASSERT(tgtmap);
2660 		if (scsi_hba_tgtmap_set_begin(tgtmap) != DDI_SUCCESS) {
2661 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2662 			    "%s: cannot set_begin tgtmap ", __func__);
2663 			rw_exit(&pwp->iports_lock);
2664 			return;
2665 		}
2666 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2667 		    "%s: set begin on tgtmap [0x%p]", __func__, (void *)tgtmap);
2668 	}
2669 	rw_exit(&pwp->iports_lock);
2670 }
2671 
2672 /*
2673  * Tell SCSA to flush the observations we've already sent (if any), as they
2674  * are no longer valid.
2675  */
2676 static void
2677 pmcs_flush_observations(pmcs_hw_t *pwp)
2678 {
2679 	pmcs_iport_t		*iport;
2680 	scsi_hba_tgtmap_t	*tgtmap;
2681 
2682 	rw_enter(&pwp->iports_lock, RW_READER);
2683 	for (iport = list_head(&pwp->iports); iport != NULL;
2684 	    iport = list_next(&pwp->iports, iport)) {
2685 		/*
2686 		 * Skip this iport if it has no PHYs up.
2687 		 */
2688 		if (!sas_phymap_uahasphys(pwp->hss_phymap, iport->ua)) {
2689 			continue;
2690 		}
2691 
2692 		tgtmap = iport->iss_tgtmap;
2693 		ASSERT(tgtmap);
2694 		if (scsi_hba_tgtmap_set_flush(tgtmap) != DDI_SUCCESS) {
2695 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2696 			    "%s: Failed set_flush on tgtmap 0x%p", __func__,
2697 			    (void *)tgtmap);
2698 		} else {
2699 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2700 			    "%s: set flush on tgtmap 0x%p", __func__,
2701 			    (void *)tgtmap);
2702 		}
2703 	}
2704 	rw_exit(&pwp->iports_lock);
2705 }
2706 
2707 /*
2708  * Report current observations to SCSA.
2709  */
2710 static boolean_t
2711 pmcs_report_observations(pmcs_hw_t *pwp)
2712 {
2713 	pmcs_iport_t		*iport;
2714 	scsi_hba_tgtmap_t	*tgtmap;
2715 	char			*ap;
2716 	pmcs_phy_t		*pptr;
2717 	uint64_t		wwn;
2718 
2719 	/*
2720 	 * Observation is stable, report what we currently see to the tgtmaps
2721 	 * for delta processing.
2722 	 */
2723 	pptr = pwp->root_phys;
2724 
2725 	while (pptr) {
2726 		pmcs_lock_phy(pptr);
2727 
2728 		/*
2729 		 * Skip PHYs that have nothing attached or are dead.
2730 		 */
2731 		if ((pptr->dtype == NOTHING) || pptr->dead) {
2732 			pmcs_unlock_phy(pptr);
2733 			pptr = pptr->sibling;
2734 			continue;
2735 		}
2736 
2737 		if (pptr->changed) {
2738 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
2739 			    "%s: oops, PHY %s changed; restart discovery",
2740 			    __func__, pptr->path);
2741 			pmcs_unlock_phy(pptr);
2742 			return (B_FALSE);
2743 		}
2744 
2745 		/*
2746 		 * Get the iport for this root PHY, then call the helper
2747 		 * to report observations for this iport's targets
2748 		 */
2749 		wwn = pmcs_barray2wwn(pptr->sas_address);
2750 		pmcs_unlock_phy(pptr);
2751 		iport = pmcs_get_iport_by_wwn(pwp, wwn);
2752 		if (iport == NULL) {
2753 			/* No iport for this tgt */
2754 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2755 			    "%s: no iport for this target", __func__);
2756 			pptr = pptr->sibling;
2757 			continue;
2758 		}
2759 
2760 		pmcs_lock_phy(pptr);
2761 		if (!iport->report_skip) {
2762 			if (pmcs_report_iport_observations(
2763 			    pwp, iport, pptr) == B_FALSE) {
2764 				pmcs_rele_iport(iport);
2765 				pmcs_unlock_phy(pptr);
2766 				return (B_FALSE);
2767 			}
2768 		}
2769 		pmcs_rele_iport(iport);
2770 		pmcs_unlock_phy(pptr);
2771 		pptr = pptr->sibling;
2772 	}
2773 
2774 	/*
2775 	 * The observation is complete, end sets. Note we will skip any
2776 	 * iports that are active, but have no PHYs in them (i.e. awaiting
2777 	 * unconfigure). Set to restart discovery if we find this.
2778 	 */
2779 	rw_enter(&pwp->iports_lock, RW_READER);
2780 	for (iport = list_head(&pwp->iports);
2781 	    iport != NULL;
2782 	    iport = list_next(&pwp->iports, iport)) {
2783 
2784 		if (iport->report_skip)
2785 			continue;		/* skip set_end */
2786 
2787 		tgtmap = iport->iss_tgtmap;
2788 		ASSERT(tgtmap);
2789 		if (scsi_hba_tgtmap_set_end(tgtmap, 0) != DDI_SUCCESS) {
2790 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2791 			    "%s: cannot set_end tgtmap ", __func__);
2792 			rw_exit(&pwp->iports_lock);
2793 			return (B_FALSE);
2794 		}
2795 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, NULL, NULL,
2796 		    "%s: set end on tgtmap [0x%p]", __func__, (void *)tgtmap);
2797 	}
2798 
2799 	/*
2800 	 * Now that discovery is complete, set up the necessary
2801 	 * DDI properties on each iport node.
2802 	 */
2803 	for (iport = list_head(&pwp->iports); iport != NULL;
2804 	    iport = list_next(&pwp->iports, iport)) {
2805 		/* Set up the 'attached-port' property on the iport */
2806 		ap = kmem_zalloc(PMCS_MAX_UA_SIZE, KM_SLEEP);
2807 		mutex_enter(&iport->lock);
2808 		pptr = iport->pptr;
2809 		mutex_exit(&iport->lock);
2810 		if (pptr == NULL) {
2811 			/*
2812 			 * This iport is down, but has not been
2813 			 * removed from our list (unconfigured).
2814 			 * Set our value to '0'.
2815 			 */
2816 			(void) snprintf(ap, 1, "%s", "0");
2817 		} else {
2818 			/* Otherwise, set it to remote phy's wwn */
2819 			pmcs_lock_phy(pptr);
2820 			wwn = pmcs_barray2wwn(pptr->sas_address);
2821 			(void) scsi_wwn_to_wwnstr(wwn, 1, ap);
2822 			pmcs_unlock_phy(pptr);
2823 		}
2824 		if (ndi_prop_update_string(DDI_DEV_T_NONE, iport->dip,
2825 		    SCSI_ADDR_PROP_ATTACHED_PORT, ap) != DDI_SUCCESS) {
2826 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed "
2827 			    "to set prop ("SCSI_ADDR_PROP_ATTACHED_PORT")",
2828 			    __func__);
2829 		}
2830 		kmem_free(ap, PMCS_MAX_UA_SIZE);
2831 	}
2832 	rw_exit(&pwp->iports_lock);
2833 
2834 	return (B_TRUE);
2835 }
2836 
2837 /*
2838  * Report observations into a particular iport's target map
2839  *
2840  * Called with phyp (and all descendents) locked
2841  */
2842 static boolean_t
2843 pmcs_report_iport_observations(pmcs_hw_t *pwp, pmcs_iport_t *iport,
2844     pmcs_phy_t *phyp)
2845 {
2846 	pmcs_phy_t		*lphyp;
2847 	scsi_hba_tgtmap_t	*tgtmap;
2848 	scsi_tgtmap_tgt_type_t	tgt_type;
2849 	char			*ua;
2850 	uint64_t		wwn;
2851 
2852 	tgtmap = iport->iss_tgtmap;
2853 	ASSERT(tgtmap);
2854 
2855 	lphyp = phyp;
2856 	while (lphyp) {
2857 		switch (lphyp->dtype) {
2858 		default:		/* Skip unknown PHYs. */
2859 			/* for non-root phys, skip to sibling */
2860 			goto next_phy;
2861 
2862 		case SATA:
2863 		case SAS:
2864 			tgt_type = SCSI_TGT_SCSI_DEVICE;
2865 			break;
2866 
2867 		case EXPANDER:
2868 			tgt_type = SCSI_TGT_SMP_DEVICE;
2869 			break;
2870 		}
2871 
2872 		if (lphyp->dead || !lphyp->configured) {
2873 			goto next_phy;
2874 		}
2875 
2876 		/*
2877 		 * Validate the PHY's SAS address
2878 		 */
2879 		if (((lphyp->sas_address[0] & 0xf0) >> 4) != NAA_IEEE_REG) {
2880 			pmcs_prt(pwp, PMCS_PRT_ERR, lphyp, NULL,
2881 			    "PHY 0x%p (%s) has invalid SAS address; "
2882 			    "will not enumerate", (void *)lphyp, lphyp->path);
2883 			goto next_phy;
2884 		}
2885 
2886 		wwn = pmcs_barray2wwn(lphyp->sas_address);
2887 		ua = scsi_wwn_to_wwnstr(wwn, 1, NULL);
2888 
2889 		pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, lphyp, NULL,
2890 		    "iport_observation: adding %s on tgtmap [0x%p] phy [0x%p]",
2891 		    ua, (void *)tgtmap, (void*)lphyp);
2892 
2893 		if (scsi_hba_tgtmap_set_add(tgtmap, tgt_type, ua, NULL) !=
2894 		    DDI_SUCCESS) {
2895 			pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,  NULL, NULL,
2896 			    "%s: failed to add address %s", __func__, ua);
2897 			scsi_free_wwnstr(ua);
2898 			return (B_FALSE);
2899 		}
2900 		scsi_free_wwnstr(ua);
2901 
2902 		if (lphyp->children) {
2903 			if (pmcs_report_iport_observations(pwp, iport,
2904 			    lphyp->children) == B_FALSE) {
2905 				return (B_FALSE);
2906 			}
2907 		}
2908 
2909 		/* for non-root phys, report siblings too */
2910 next_phy:
2911 		if (IS_ROOT_PHY(lphyp)) {
2912 			lphyp = NULL;
2913 		} else {
2914 			lphyp = lphyp->sibling;
2915 		}
2916 	}
2917 
2918 	return (B_TRUE);
2919 }
2920 
2921 /*
2922  * Check for and configure new devices.
2923  *
2924  * If the changed device is a SATA device, add a SATA device.
2925  *
2926  * If the changed device is a SAS device, add a SAS device.
2927  *
2928  * If the changed device is an EXPANDER device, do a REPORT
2929  * GENERAL SMP command to find out the number of contained phys.
2930  *
2931  * For each number of contained phys, allocate a phy, do a
2932  * DISCOVERY SMP command to find out what kind of device it
2933  * is and add it to the linked list of phys on the *next* level.
2934  *
2935  * NOTE: pptr passed in by the caller will be a root PHY
2936  */
2937 static int
2938 pmcs_configure_new_devices(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
2939 {
2940 	int rval = 0;
2941 	pmcs_iport_t *iport;
2942 	pmcs_phy_t *pnext, *orig_pptr = pptr, *root_phy, *pchild;
2943 	uint64_t wwn;
2944 
2945 	/*
2946 	 * First, walk through each PHY at this level
2947 	 */
2948 	while (pptr) {
2949 		pmcs_lock_phy(pptr);
2950 		pnext = pptr->sibling;
2951 
2952 		/*
2953 		 * Set the new dtype if it has changed
2954 		 */
2955 		if ((pptr->pend_dtype != NEW) &&
2956 		    (pptr->pend_dtype != pptr->dtype)) {
2957 			pptr->dtype = pptr->pend_dtype;
2958 		}
2959 
2960 		if (pptr->changed == 0 || pptr->dead || pptr->configured) {
2961 			goto next_phy;
2962 		}
2963 
2964 		/*
2965 		 * Confirm that this target's iport is configured
2966 		 */
2967 		root_phy = pmcs_get_root_phy(pptr);
2968 		wwn = pmcs_barray2wwn(root_phy->sas_address);
2969 		pmcs_unlock_phy(pptr);
2970 		iport = pmcs_get_iport_by_wwn(pwp, wwn);
2971 		if (iport == NULL) {
2972 			/* No iport for this tgt, restart */
2973 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
2974 			    "%s: iport not yet configured, "
2975 			    "retry discovery", __func__);
2976 			pnext = NULL;
2977 			rval = -1;
2978 			pmcs_lock_phy(pptr);
2979 			goto next_phy;
2980 		}
2981 
2982 		pmcs_lock_phy(pptr);
2983 		switch (pptr->dtype) {
2984 		case NOTHING:
2985 			pptr->changed = 0;
2986 			break;
2987 		case SATA:
2988 		case SAS:
2989 			pptr->iport = iport;
2990 			pmcs_new_tport(pwp, pptr);
2991 			break;
2992 		case EXPANDER:
2993 			pmcs_configure_expander(pwp, pptr, iport);
2994 			break;
2995 		}
2996 		pmcs_rele_iport(iport);
2997 
2998 		mutex_enter(&pwp->config_lock);
2999 		if (pwp->config_changed) {
3000 			mutex_exit(&pwp->config_lock);
3001 			pnext = NULL;
3002 			goto next_phy;
3003 		}
3004 		mutex_exit(&pwp->config_lock);
3005 
3006 next_phy:
3007 		pmcs_unlock_phy(pptr);
3008 		pptr = pnext;
3009 	}
3010 
3011 	if (rval != 0) {
3012 		return (rval);
3013 	}
3014 
3015 	/*
3016 	 * Now walk through each PHY again, recalling ourselves if they
3017 	 * have children
3018 	 */
3019 	pptr = orig_pptr;
3020 	while (pptr) {
3021 		pmcs_lock_phy(pptr);
3022 		pnext = pptr->sibling;
3023 		pchild = pptr->children;
3024 		pmcs_unlock_phy(pptr);
3025 
3026 		if (pchild) {
3027 			rval = pmcs_configure_new_devices(pwp, pchild);
3028 			if (rval != 0) {
3029 				break;
3030 			}
3031 		}
3032 
3033 		pptr = pnext;
3034 	}
3035 
3036 	return (rval);
3037 }
3038 
3039 /*
3040  * Set all phys and descendent phys as changed if changed == B_TRUE, otherwise
3041  * mark them all as not changed.
3042  *
3043  * Called with parent PHY locked.
3044  */
3045 void
3046 pmcs_set_changed(pmcs_hw_t *pwp, pmcs_phy_t *parent, boolean_t changed,
3047     int level)
3048 {
3049 	pmcs_phy_t *pptr;
3050 
3051 	if (level == 0) {
3052 		if (changed) {
3053 			PHY_CHANGED(pwp, parent);
3054 		} else {
3055 			parent->changed = 0;
3056 		}
3057 		if (parent->dtype == EXPANDER && parent->level) {
3058 			parent->width = 1;
3059 		}
3060 		if (parent->children) {
3061 			pmcs_set_changed(pwp, parent->children, changed,
3062 			    level + 1);
3063 		}
3064 	} else {
3065 		pptr = parent;
3066 		while (pptr) {
3067 			if (changed) {
3068 				PHY_CHANGED(pwp, pptr);
3069 			} else {
3070 				pptr->changed = 0;
3071 			}
3072 			if (pptr->dtype == EXPANDER && pptr->level) {
3073 				pptr->width = 1;
3074 			}
3075 			if (pptr->children) {
3076 				pmcs_set_changed(pwp, pptr->children, changed,
3077 				    level + 1);
3078 			}
3079 			pptr = pptr->sibling;
3080 		}
3081 	}
3082 }
3083 
3084 /*
3085  * Take the passed phy mark it and its descendants as dead.
3086  * Fire up reconfiguration to abort commands and bury it.
3087  *
3088  * Called with the parent PHY locked.
3089  */
3090 void
3091 pmcs_kill_changed(pmcs_hw_t *pwp, pmcs_phy_t *parent, int level)
3092 {
3093 	pmcs_phy_t *pptr = parent;
3094 
3095 	while (pptr) {
3096 		pptr->link_rate = 0;
3097 		pptr->abort_sent = 0;
3098 		pptr->abort_pending = 1;
3099 		SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
3100 		pptr->need_rl_ext = 0;
3101 
3102 		if (pptr->dead == 0) {
3103 			PHY_CHANGED(pwp, pptr);
3104 			RESTART_DISCOVERY(pwp);
3105 		}
3106 
3107 		pptr->dead = 1;
3108 
3109 		if (pptr->children) {
3110 			pmcs_kill_changed(pwp, pptr->children, level + 1);
3111 		}
3112 
3113 		/*
3114 		 * Only kill siblings at level > 0
3115 		 */
3116 		if (level == 0) {
3117 			return;
3118 		}
3119 
3120 		pptr = pptr->sibling;
3121 	}
3122 }
3123 
3124 /*
3125  * Go through every PHY and clear any that are dead (unless they're expanders)
3126  */
3127 static void
3128 pmcs_clear_phys(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3129 {
3130 	pmcs_phy_t *pnext, *phyp;
3131 
3132 	phyp = pptr;
3133 	while (phyp) {
3134 		if (IS_ROOT_PHY(phyp)) {
3135 			pmcs_lock_phy(phyp);
3136 		}
3137 
3138 		if ((phyp->dtype != EXPANDER) && phyp->dead) {
3139 			pmcs_clear_phy(pwp, phyp);
3140 		}
3141 
3142 		if (phyp->children) {
3143 			pmcs_clear_phys(pwp, phyp->children);
3144 		}
3145 
3146 		pnext = phyp->sibling;
3147 
3148 		if (IS_ROOT_PHY(phyp)) {
3149 			pmcs_unlock_phy(phyp);
3150 		}
3151 
3152 		phyp = pnext;
3153 	}
3154 }
3155 
3156 /*
3157  * Clear volatile parts of a phy.  Called with PHY locked.
3158  */
3159 void
3160 pmcs_clear_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3161 {
3162 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "%s: %s",
3163 	    __func__, pptr->path);
3164 	ASSERT(mutex_owned(&pptr->phy_lock));
3165 	/* keep sibling */
3166 	/* keep children */
3167 	/* keep parent */
3168 	pptr->device_id = PMCS_INVALID_DEVICE_ID;
3169 	/* keep hw_event_ack */
3170 	pptr->ncphy = 0;
3171 	/* keep phynum */
3172 	pptr->width = 0;
3173 	pptr->ds_recovery_retries = 0;
3174 	pptr->ds_prev_good_recoveries = 0;
3175 	pptr->last_good_recovery = 0;
3176 	pptr->prev_recovery = 0;
3177 
3178 	/* keep dtype */
3179 	pptr->config_stop = 0;
3180 	pptr->spinup_hold = 0;
3181 	pptr->atdt = 0;
3182 	/* keep portid */
3183 	pptr->link_rate = 0;
3184 	pptr->valid_device_id = 0;
3185 	pptr->abort_sent = 0;
3186 	pptr->abort_pending = 0;
3187 	pptr->need_rl_ext = 0;
3188 	pptr->subsidiary = 0;
3189 	pptr->configured = 0;
3190 	pptr->deregister_wait = 0;
3191 	pptr->reenumerate = 0;
3192 	/* Only mark dead if it's not a root PHY and its dtype isn't NOTHING */
3193 	/* XXX: What about directly attached disks? */
3194 	if (!IS_ROOT_PHY(pptr) && (pptr->dtype != NOTHING))
3195 		pptr->dead = 1;
3196 	pptr->changed = 0;
3197 	/* keep SAS address */
3198 	/* keep path */
3199 	/* keep ref_count */
3200 	/* Don't clear iport on root PHYs - they are handled in pmcs_intr.c */
3201 	if (!IS_ROOT_PHY(pptr)) {
3202 		pptr->last_iport = pptr->iport;
3203 		pptr->iport = NULL;
3204 	}
3205 	/* keep target */
3206 }
3207 
3208 /*
3209  * Allocate softstate for this target if there isn't already one.  If there
3210  * is, just redo our internal configuration.  If it is actually "new", we'll
3211  * soon get a tran_tgt_init for it.
3212  *
3213  * Called with PHY locked.
3214  */
3215 static void
3216 pmcs_new_tport(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3217 {
3218 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "%s: phy 0x%p @ %s",
3219 	    __func__, (void *)pptr, pptr->path);
3220 
3221 	if (pmcs_configure_phy(pwp, pptr) == B_FALSE) {
3222 		/*
3223 		 * If the config failed, mark the PHY as changed.
3224 		 */
3225 		PHY_CHANGED(pwp, pptr);
3226 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3227 		    "%s: pmcs_configure_phy failed for phy 0x%p", __func__,
3228 		    (void *)pptr);
3229 		return;
3230 	}
3231 
3232 	/* Mark PHY as no longer changed */
3233 	pptr->changed = 0;
3234 
3235 	/*
3236 	 * If the PHY has no target pointer:
3237 	 *
3238 	 * If it's a root PHY, see if another PHY in the iport holds the
3239 	 * target pointer (primary PHY changed).  If so, move it over.
3240 	 *
3241 	 * If it's not a root PHY, see if there's a PHY on the dead_phys
3242 	 * list that matches.
3243 	 */
3244 	if (pptr->target == NULL) {
3245 		if (IS_ROOT_PHY(pptr)) {
3246 			pmcs_phy_t *rphy = pwp->root_phys;
3247 
3248 			while (rphy) {
3249 				if (rphy == pptr) {
3250 					rphy = rphy->sibling;
3251 					continue;
3252 				}
3253 
3254 				mutex_enter(&rphy->phy_lock);
3255 				if ((rphy->iport == pptr->iport) &&
3256 				    (rphy->target != NULL)) {
3257 					mutex_enter(&rphy->target->statlock);
3258 					pptr->target = rphy->target;
3259 					rphy->target = NULL;
3260 					pptr->target->phy = pptr;
3261 					/* The target is now on pptr */
3262 					mutex_exit(&pptr->target->statlock);
3263 					mutex_exit(&rphy->phy_lock);
3264 					pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
3265 					    pptr, pptr->target,
3266 					    "%s: Moved target from %s to %s",
3267 					    __func__, rphy->path, pptr->path);
3268 					break;
3269 				}
3270 				mutex_exit(&rphy->phy_lock);
3271 
3272 				rphy = rphy->sibling;
3273 			}
3274 		} else {
3275 			pmcs_reap_dead_phy(pptr);
3276 		}
3277 	}
3278 
3279 	/*
3280 	 * Only assign the device if there is a target for this PHY with a
3281 	 * matching SAS address.  If an iport is disconnected from one piece
3282 	 * of storage and connected to another within the iport stabilization
3283 	 * time, we can get the PHY/target mismatch situation.
3284 	 *
3285 	 * Otherwise, it'll get done in tran_tgt_init.
3286 	 */
3287 	if (pptr->target) {
3288 		mutex_enter(&pptr->target->statlock);
3289 		if (pmcs_phy_target_match(pptr) == B_FALSE) {
3290 			mutex_exit(&pptr->target->statlock);
3291 			if (!IS_ROOT_PHY(pptr)) {
3292 				pmcs_dec_phy_ref_count(pptr);
3293 			}
3294 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3295 			    "%s: Not assigning existing tgt %p for PHY %p "
3296 			    "(WWN mismatch)", __func__, (void *)pptr->target,
3297 			    (void *)pptr);
3298 			pptr->target = NULL;
3299 			return;
3300 		}
3301 
3302 		if (!pmcs_assign_device(pwp, pptr->target)) {
3303 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
3304 			    "%s: pmcs_assign_device failed for target 0x%p",
3305 			    __func__, (void *)pptr->target);
3306 		}
3307 		mutex_exit(&pptr->target->statlock);
3308 	}
3309 }
3310 
3311 /*
3312  * Called with PHY lock held.
3313  */
3314 static boolean_t
3315 pmcs_configure_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3316 {
3317 	char *dtype;
3318 
3319 	ASSERT(mutex_owned(&pptr->phy_lock));
3320 
3321 	/*
3322 	 * Mark this device as no longer changed.
3323 	 */
3324 	pptr->changed = 0;
3325 
3326 	/*
3327 	 * If we don't have a device handle, get one.
3328 	 */
3329 	if (pmcs_get_device_handle(pwp, pptr)) {
3330 		return (B_FALSE);
3331 	}
3332 
3333 	pptr->configured = 1;
3334 
3335 	switch (pptr->dtype) {
3336 	case SAS:
3337 		dtype = "SAS";
3338 		break;
3339 	case SATA:
3340 		dtype = "SATA";
3341 		break;
3342 	case EXPANDER:
3343 		dtype = "SMP";
3344 		break;
3345 	default:
3346 		dtype = "???";
3347 	}
3348 
3349 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "config_dev: %s "
3350 	    "dev %s " SAS_ADDR_FMT " dev id 0x%x lr 0x%x", dtype, pptr->path,
3351 	    SAS_ADDR_PRT(pptr->sas_address), pptr->device_id, pptr->link_rate);
3352 
3353 	return (B_TRUE);
3354 }
3355 
3356 /*
3357  * Called with PHY locked
3358  */
3359 static void
3360 pmcs_configure_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr, pmcs_iport_t *iport)
3361 {
3362 	pmcs_phy_t *ctmp, *clist = NULL, *cnext;
3363 	int result, i, nphy = 0;
3364 	boolean_t root_phy = B_FALSE;
3365 
3366 	ASSERT(iport);
3367 
3368 	/*
3369 	 * Step 1- clear our "changed" bit. If we need to retry/restart due
3370 	 * to resource shortages, we'll set it again. While we're doing
3371 	 * configuration, other events may set it again as well.  If the PHY
3372 	 * is a root PHY and is currently marked as having changed, reset the
3373 	 * config_stop timer as well.
3374 	 */
3375 	if (IS_ROOT_PHY(pptr) && pptr->changed) {
3376 		pptr->config_stop = ddi_get_lbolt() +
3377 		    drv_usectohz(PMCS_MAX_CONFIG_TIME);
3378 	}
3379 	pptr->changed = 0;
3380 
3381 	/*
3382 	 * Step 2- make sure we don't overflow
3383 	 */
3384 	if (pptr->level == PMCS_MAX_XPND-1) {
3385 		pmcs_prt(pwp, PMCS_PRT_WARN, pptr, NULL,
3386 		    "%s: SAS expansion tree too deep", __func__);
3387 		return;
3388 	}
3389 
3390 	/*
3391 	 * Step 3- Check if this expander is part of a wide phy that has
3392 	 * already been configured.
3393 	 *
3394 	 * This is known by checking this level for another EXPANDER device
3395 	 * with the same SAS address and isn't already marked as a subsidiary
3396 	 * phy and a parent whose SAS address is the same as our SAS address
3397 	 * (if there are parents).
3398 	 */
3399 	if (!IS_ROOT_PHY(pptr)) {
3400 		/*
3401 		 * No need to lock the parent here because we're in discovery
3402 		 * and the only time a PHY's children pointer can change is
3403 		 * in discovery; either in pmcs_clear_expander (which has
3404 		 * already been called) or here, down below.  Plus, trying to
3405 		 * grab the parent's lock here can cause deadlock.
3406 		 */
3407 		ctmp = pptr->parent->children;
3408 	} else {
3409 		ctmp = pwp->root_phys;
3410 		root_phy = B_TRUE;
3411 	}
3412 
3413 	while (ctmp) {
3414 		/*
3415 		 * If we've checked all PHYs up to pptr, we stop. Otherwise,
3416 		 * we'll be checking for a primary PHY with a higher PHY
3417 		 * number than pptr, which will never happen.  The primary
3418 		 * PHY on non-root expanders will ALWAYS be the lowest
3419 		 * numbered PHY.
3420 		 */
3421 		if (ctmp == pptr) {
3422 			break;
3423 		}
3424 
3425 		/*
3426 		 * If pptr and ctmp are root PHYs, just grab the mutex on
3427 		 * ctmp.  No need to lock the entire tree.  If they are not
3428 		 * root PHYs, there is no need to lock since a non-root PHY's
3429 		 * SAS address and other characteristics can only change in
3430 		 * discovery anyway.
3431 		 */
3432 		if (root_phy) {
3433 			mutex_enter(&ctmp->phy_lock);
3434 		}
3435 
3436 		if (ctmp->dtype == EXPANDER && ctmp->width &&
3437 		    memcmp(ctmp->sas_address, pptr->sas_address, 8) == 0) {
3438 			int widephy = 0;
3439 			/*
3440 			 * If these phys are not root PHYs, compare their SAS
3441 			 * addresses too.
3442 			 */
3443 			if (!root_phy) {
3444 				if (memcmp(ctmp->parent->sas_address,
3445 				    pptr->parent->sas_address, 8) == 0) {
3446 					widephy = 1;
3447 				}
3448 			} else {
3449 				widephy = 1;
3450 			}
3451 			if (widephy) {
3452 				ctmp->width++;
3453 				pptr->subsidiary = 1;
3454 
3455 				/*
3456 				 * Update the primary PHY's attached-port-pm
3457 				 * and target-port-pm information with the info
3458 				 * from this subsidiary
3459 				 */
3460 				pmcs_update_phy_pm_props(ctmp,
3461 				    pptr->att_port_pm_tmp,
3462 				    pptr->tgt_port_pm_tmp, B_TRUE);
3463 
3464 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3465 				    "%s: PHY %s part of wide PHY %s "
3466 				    "(now %d wide)", __func__, pptr->path,
3467 				    ctmp->path, ctmp->width);
3468 				if (root_phy) {
3469 					mutex_exit(&ctmp->phy_lock);
3470 				}
3471 				return;
3472 			}
3473 		}
3474 
3475 		cnext = ctmp->sibling;
3476 		if (root_phy) {
3477 			mutex_exit(&ctmp->phy_lock);
3478 		}
3479 		ctmp = cnext;
3480 	}
3481 
3482 	/*
3483 	 * Step 4- If we don't have a device handle, get one.  Since this
3484 	 * is the primary PHY, make sure subsidiary is cleared.
3485 	 */
3486 	pptr->subsidiary = 0;
3487 	pptr->iport = iport;
3488 	if (pmcs_get_device_handle(pwp, pptr)) {
3489 		goto out;
3490 	}
3491 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, "Config expander %s "
3492 	    SAS_ADDR_FMT " dev id 0x%x lr 0x%x", pptr->path,
3493 	    SAS_ADDR_PRT(pptr->sas_address), pptr->device_id, pptr->link_rate);
3494 
3495 	/*
3496 	 * Step 5- figure out how many phys are in this expander.
3497 	 */
3498 	nphy = pmcs_expander_get_nphy(pwp, pptr);
3499 	if (nphy <= 0) {
3500 		if (nphy == 0 && ddi_get_lbolt() < pptr->config_stop) {
3501 			PHY_CHANGED(pwp, pptr);
3502 			RESTART_DISCOVERY(pwp);
3503 		} else {
3504 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3505 			    "%s: Retries exhausted for %s, killing", __func__,
3506 			    pptr->path);
3507 			pptr->config_stop = 0;
3508 			pmcs_kill_changed(pwp, pptr, 0);
3509 		}
3510 		goto out;
3511 	}
3512 
3513 	/*
3514 	 * Step 6- Allocate a list of phys for this expander and figure out
3515 	 * what each one is.
3516 	 */
3517 	for (i = 0; i < nphy; i++) {
3518 		ctmp = kmem_cache_alloc(pwp->phy_cache, KM_SLEEP);
3519 		bzero(ctmp, sizeof (pmcs_phy_t));
3520 		ctmp->device_id = PMCS_INVALID_DEVICE_ID;
3521 		ctmp->sibling = clist;
3522 		ctmp->pend_dtype = NEW;	/* Init pending dtype */
3523 		ctmp->config_stop = ddi_get_lbolt() +
3524 		    drv_usectohz(PMCS_MAX_CONFIG_TIME);
3525 		clist = ctmp;
3526 	}
3527 
3528 	mutex_enter(&pwp->config_lock);
3529 	if (pwp->config_changed) {
3530 		RESTART_DISCOVERY_LOCKED(pwp);
3531 		mutex_exit(&pwp->config_lock);
3532 		/*
3533 		 * Clean up the newly allocated PHYs and return
3534 		 */
3535 		while (clist) {
3536 			ctmp = clist->sibling;
3537 			kmem_cache_free(pwp->phy_cache, clist);
3538 			clist = ctmp;
3539 		}
3540 		return;
3541 	}
3542 	mutex_exit(&pwp->config_lock);
3543 
3544 	/*
3545 	 * Step 7- Now fill in the rest of the static portions of the phy.
3546 	 */
3547 	for (i = 0, ctmp = clist; ctmp; ctmp = ctmp->sibling, i++) {
3548 		ctmp->parent = pptr;
3549 		ctmp->pwp = pwp;
3550 		ctmp->level = pptr->level+1;
3551 		ctmp->portid = pptr->portid;
3552 		if (ctmp->tolerates_sas2) {
3553 			ASSERT(i < SAS2_PHYNUM_MAX);
3554 			ctmp->phynum = i & SAS2_PHYNUM_MASK;
3555 		} else {
3556 			ASSERT(i < SAS_PHYNUM_MAX);
3557 			ctmp->phynum = i & SAS_PHYNUM_MASK;
3558 		}
3559 		pmcs_phy_name(pwp, ctmp, ctmp->path, sizeof (ctmp->path));
3560 		pmcs_lock_phy(ctmp);
3561 	}
3562 
3563 	/*
3564 	 * Step 8- Discover things about each phy in the expander.
3565 	 */
3566 	for (i = 0, ctmp = clist; ctmp; ctmp = ctmp->sibling, i++) {
3567 		result = pmcs_expander_content_discover(pwp, pptr, ctmp);
3568 		if (result <= 0) {
3569 			if (ddi_get_lbolt() < pptr->config_stop) {
3570 				PHY_CHANGED(pwp, pptr);
3571 				RESTART_DISCOVERY(pwp);
3572 			} else {
3573 				pptr->config_stop = 0;
3574 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3575 				    "%s: Retries exhausted for %s, killing",
3576 				    __func__, pptr->path);
3577 				pmcs_kill_changed(pwp, pptr, 0);
3578 			}
3579 			goto out;
3580 		}
3581 
3582 		/* Set pend_dtype to dtype for 1st time initialization */
3583 		ctmp->pend_dtype = ctmp->dtype;
3584 	}
3585 
3586 	/*
3587 	 * Step 9: Install the new list on the next level. There should
3588 	 * typically be no children pointer on this PHY.  There is one known
3589 	 * case where this can happen, though.  If a root PHY goes down and
3590 	 * comes back up before discovery can run, we will fail to remove the
3591 	 * children from that PHY since it will no longer be marked dead.
3592 	 * However, in this case, all children should also be marked dead.  If
3593 	 * we see that, take those children and put them on the dead_phys list.
3594 	 */
3595 	if (pptr->children != NULL) {
3596 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
3597 		    "%s: Expander @ %s still has children: Clean up",
3598 		    __func__, pptr->path);
3599 		pmcs_add_dead_phys(pwp, pptr->children);
3600 	}
3601 
3602 	/*
3603 	 * Set the new children pointer for this expander
3604 	 */
3605 	pptr->children = clist;
3606 	clist = NULL;
3607 	pptr->ncphy = nphy;
3608 	pptr->configured = 1;
3609 
3610 	/*
3611 	 * We only set width if we're greater than level 0.
3612 	 */
3613 	if (pptr->level) {
3614 		pptr->width = 1;
3615 	}
3616 
3617 	/*
3618 	 * Now tell the rest of the world about us, as an SMP node.
3619 	 */
3620 	pptr->iport = iport;
3621 	pmcs_new_tport(pwp, pptr);
3622 
3623 out:
3624 	while (clist) {
3625 		ctmp = clist->sibling;
3626 		pmcs_unlock_phy(clist);
3627 		kmem_cache_free(pwp->phy_cache, clist);
3628 		clist = ctmp;
3629 	}
3630 }
3631 
3632 /*
3633  * 2. Check expanders marked changed (but not dead) to see if they still have
3634  * the same number of phys and the same SAS address. Mark them, their subsidiary
3635  * phys (if wide) and their descendents dead if anything has changed. Check the
3636  * the devices they contain to see if *they* have changed. If they've changed
3637  * from type NOTHING we leave them marked changed to be configured later
3638  * (picking up a new SAS address and link rate if possible). Otherwise, any
3639  * change in type, SAS address or removal of target role will cause us to
3640  * mark them (and their descendents) as dead and cause any pending commands
3641  * and associated devices to be removed.
3642  *
3643  * Called with PHY (pptr) locked.
3644  */
3645 
3646 static void
3647 pmcs_check_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3648 {
3649 	int nphy, result;
3650 	pmcs_phy_t *ctmp, *local, *local_list = NULL, *local_tail = NULL;
3651 	boolean_t kill_changed, changed;
3652 
3653 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3654 	    "%s: check %s", __func__, pptr->path);
3655 
3656 	/*
3657 	 * Step 1: Mark phy as not changed. We will mark it changed if we need
3658 	 * to retry.
3659 	 */
3660 	pptr->changed = 0;
3661 
3662 	/*
3663 	 * Reset the config_stop time. Although we're not actually configuring
3664 	 * anything here, we do want some indication of when to give up trying
3665 	 * if we can't communicate with the expander.
3666 	 */
3667 	pptr->config_stop = ddi_get_lbolt() +
3668 	    drv_usectohz(PMCS_MAX_CONFIG_TIME);
3669 
3670 	/*
3671 	 * Step 2: Figure out how many phys are in this expander. If
3672 	 * pmcs_expander_get_nphy returns 0 we ran out of resources,
3673 	 * so reschedule and try later. If it returns another error,
3674 	 * just return.
3675 	 */
3676 	nphy = pmcs_expander_get_nphy(pwp, pptr);
3677 	if (nphy <= 0) {
3678 		if ((nphy == 0) && (ddi_get_lbolt() < pptr->config_stop)) {
3679 			PHY_CHANGED(pwp, pptr);
3680 			RESTART_DISCOVERY(pwp);
3681 		} else {
3682 			pptr->config_stop = 0;
3683 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3684 			    "%s: Retries exhausted for %s, killing", __func__,
3685 			    pptr->path);
3686 			pmcs_kill_changed(pwp, pptr, 0);
3687 		}
3688 		return;
3689 	}
3690 
3691 	/*
3692 	 * Step 3: If the number of phys don't agree, kill the old sub-tree.
3693 	 */
3694 	if (nphy != pptr->ncphy) {
3695 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3696 		    "%s: number of contained phys for %s changed from %d to %d",
3697 		    __func__, pptr->path, pptr->ncphy, nphy);
3698 		/*
3699 		 * Force a rescan of this expander after dead contents
3700 		 * are cleared and removed.
3701 		 */
3702 		pmcs_kill_changed(pwp, pptr, 0);
3703 		return;
3704 	}
3705 
3706 	/*
3707 	 * Step 4: if we're at the bottom of the stack, we're done
3708 	 * (we can't have any levels below us)
3709 	 */
3710 	if (pptr->level == PMCS_MAX_XPND-1) {
3711 		return;
3712 	}
3713 
3714 	/*
3715 	 * Step 5: Discover things about each phy in this expander.  We do
3716 	 * this by walking the current list of contained phys and doing a
3717 	 * content discovery for it to a local phy.
3718 	 */
3719 	ctmp = pptr->children;
3720 	ASSERT(ctmp);
3721 	if (ctmp == NULL) {
3722 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3723 		    "%s: No children attached to expander @ %s?", __func__,
3724 		    pptr->path);
3725 		return;
3726 	}
3727 
3728 	while (ctmp) {
3729 		/*
3730 		 * Allocate a local PHY to contain the proposed new contents
3731 		 * and link it to the rest of the local PHYs so that they
3732 		 * can all be freed later.
3733 		 */
3734 		local = pmcs_clone_phy(ctmp);
3735 
3736 		if (local_list == NULL) {
3737 			local_list = local;
3738 			local_tail = local;
3739 		} else {
3740 			local_tail->sibling = local;
3741 			local_tail = local;
3742 		}
3743 
3744 		/*
3745 		 * Need to lock the local PHY since pmcs_expander_content_
3746 		 * discovery may call pmcs_clear_phy on it, which expects
3747 		 * the PHY to be locked.
3748 		 */
3749 		pmcs_lock_phy(local);
3750 		result = pmcs_expander_content_discover(pwp, pptr, local);
3751 		pmcs_unlock_phy(local);
3752 		if (result <= 0) {
3753 			if (ddi_get_lbolt() < pptr->config_stop) {
3754 				PHY_CHANGED(pwp, pptr);
3755 				RESTART_DISCOVERY(pwp);
3756 			} else {
3757 				pptr->config_stop = 0;
3758 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3759 				    "%s: Retries exhausted for %s, killing",
3760 				    __func__, pptr->path);
3761 				pmcs_kill_changed(pwp, pptr, 0);
3762 			}
3763 
3764 			/*
3765 			 * Release all the local PHYs that we allocated.
3766 			 */
3767 			pmcs_free_phys(pwp, local_list);
3768 			return;
3769 		}
3770 
3771 		ctmp = ctmp->sibling;
3772 	}
3773 
3774 	/*
3775 	 * Step 6: Compare the local PHY's contents to our current PHY.  If
3776 	 * there are changes, take the appropriate action.
3777 	 * This is done in two steps (step 5 above, and 6 here) so that if we
3778 	 * have to bail during this process (e.g. pmcs_expander_content_discover
3779 	 * fails), we haven't actually changed the state of any of the real
3780 	 * PHYs.  Next time we come through here, we'll be starting over from
3781 	 * scratch.  This keeps us from marking a changed PHY as no longer
3782 	 * changed, but then having to bail only to come back next time and
3783 	 * think that the PHY hadn't changed.  If this were to happen, we
3784 	 * would fail to properly configure the device behind this PHY.
3785 	 */
3786 	local = local_list;
3787 	ctmp = pptr->children;
3788 
3789 	while (ctmp) {
3790 		changed = B_FALSE;
3791 		kill_changed = B_FALSE;
3792 
3793 		/*
3794 		 * We set local to local_list prior to this loop so that we
3795 		 * can simply walk the local_list while we walk this list.  The
3796 		 * two lists should be completely in sync.
3797 		 *
3798 		 * Clear the changed flag here.
3799 		 */
3800 		ctmp->changed = 0;
3801 
3802 		if (ctmp->dtype != local->dtype) {
3803 			if (ctmp->dtype != NOTHING) {
3804 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3805 				    "%s: %s type changed from %s to %s "
3806 				    "(killing)", __func__, ctmp->path,
3807 				    PHY_TYPE(ctmp), PHY_TYPE(local));
3808 				/*
3809 				 * Force a rescan of this expander after dead
3810 				 * contents are cleared and removed.
3811 				 */
3812 				changed = B_TRUE;
3813 				kill_changed = B_TRUE;
3814 			} else {
3815 				changed = B_TRUE;
3816 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3817 				    "%s: %s type changed from NOTHING to %s",
3818 				    __func__, ctmp->path, PHY_TYPE(local));
3819 				/*
3820 				 * Since this PHY was nothing and is now
3821 				 * something, reset the config_stop timer.
3822 				 */
3823 				ctmp->config_stop = ddi_get_lbolt() +
3824 				    drv_usectohz(PMCS_MAX_CONFIG_TIME);
3825 			}
3826 
3827 		} else if (ctmp->atdt != local->atdt) {
3828 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL, "%s: "
3829 			    "%s attached device type changed from %d to %d "
3830 			    "(killing)", __func__, ctmp->path, ctmp->atdt,
3831 			    local->atdt);
3832 			/*
3833 			 * Force a rescan of this expander after dead
3834 			 * contents are cleared and removed.
3835 			 */
3836 			changed = B_TRUE;
3837 
3838 			if (local->atdt == 0) {
3839 				kill_changed = B_TRUE;
3840 			}
3841 		} else if (ctmp->link_rate != local->link_rate) {
3842 			pmcs_prt(pwp, PMCS_PRT_INFO, ctmp, NULL, "%s: %s "
3843 			    "changed speed from %s to %s", __func__, ctmp->path,
3844 			    pmcs_get_rate(ctmp->link_rate),
3845 			    pmcs_get_rate(local->link_rate));
3846 			/* If the speed changed from invalid, force rescan */
3847 			if (!PMCS_VALID_LINK_RATE(ctmp->link_rate)) {
3848 				changed = B_TRUE;
3849 				RESTART_DISCOVERY(pwp);
3850 			} else {
3851 				/* Just update to the new link rate */
3852 				ctmp->link_rate = local->link_rate;
3853 			}
3854 
3855 			if (!PMCS_VALID_LINK_RATE(local->link_rate)) {
3856 				kill_changed = B_TRUE;
3857 			}
3858 		} else if (memcmp(ctmp->sas_address, local->sas_address,
3859 		    sizeof (ctmp->sas_address)) != 0) {
3860 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3861 			    "%s: SAS Addr for %s changed from " SAS_ADDR_FMT
3862 			    "to " SAS_ADDR_FMT " (kill old tree)", __func__,
3863 			    ctmp->path, SAS_ADDR_PRT(ctmp->sas_address),
3864 			    SAS_ADDR_PRT(local->sas_address));
3865 			/*
3866 			 * Force a rescan of this expander after dead
3867 			 * contents are cleared and removed.
3868 			 */
3869 			changed = B_TRUE;
3870 		} else {
3871 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
3872 			    "%s: %s looks the same (type %s)",
3873 			    __func__, ctmp->path, PHY_TYPE(ctmp));
3874 			/*
3875 			 * If EXPANDER, still mark it changed so we
3876 			 * re-evaluate its contents.  If it's not an expander,
3877 			 * but it hasn't been configured, also mark it as
3878 			 * changed so that it will undergo configuration.
3879 			 */
3880 			if (ctmp->dtype == EXPANDER) {
3881 				changed = B_TRUE;
3882 			} else if ((ctmp->dtype != NOTHING) &&
3883 			    !ctmp->configured) {
3884 				ctmp->changed = 1;
3885 			} else {
3886 				/* It simply hasn't changed */
3887 				ctmp->changed = 0;
3888 			}
3889 		}
3890 
3891 		/*
3892 		 * If the PHY changed, call pmcs_kill_changed if indicated,
3893 		 * update its contents to reflect its current state and mark it
3894 		 * as changed.
3895 		 */
3896 		if (changed) {
3897 			/*
3898 			 * pmcs_kill_changed will mark the PHY as changed, so
3899 			 * only do PHY_CHANGED if we did not do kill_changed.
3900 			 */
3901 			if (kill_changed) {
3902 				pmcs_kill_changed(pwp, ctmp, 0);
3903 			} else {
3904 				/*
3905 				 * If we're not killing the device, it's not
3906 				 * dead.  Mark the PHY as changed.
3907 				 */
3908 				PHY_CHANGED(pwp, ctmp);
3909 
3910 				if (ctmp->dead) {
3911 					pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
3912 					    ctmp, NULL, "%s: Unmarking PHY %s "
3913 					    "dead, restarting discovery",
3914 					    __func__, ctmp->path);
3915 					ctmp->dead = 0;
3916 					RESTART_DISCOVERY(pwp);
3917 				}
3918 			}
3919 
3920 			/*
3921 			 * If the dtype of this PHY is now NOTHING, mark it as
3922 			 * unconfigured.  Set pend_dtype to what the new dtype
3923 			 * is.  It'll get updated at the end of the discovery
3924 			 * process.
3925 			 */
3926 			if (local->dtype == NOTHING) {
3927 				bzero(ctmp->sas_address,
3928 				    sizeof (local->sas_address));
3929 				ctmp->atdt = 0;
3930 				ctmp->link_rate = 0;
3931 				ctmp->pend_dtype = NOTHING;
3932 				ctmp->configured = 0;
3933 			} else {
3934 				(void) memcpy(ctmp->sas_address,
3935 				    local->sas_address,
3936 				    sizeof (local->sas_address));
3937 				ctmp->atdt = local->atdt;
3938 				ctmp->link_rate = local->link_rate;
3939 				ctmp->pend_dtype = local->dtype;
3940 			}
3941 		}
3942 
3943 		local = local->sibling;
3944 		ctmp = ctmp->sibling;
3945 	}
3946 
3947 	/*
3948 	 * If we got to here, that means we were able to see all the PHYs
3949 	 * and we can now update all of the real PHYs with the information
3950 	 * we got on the local PHYs.  Once that's done, free all the local
3951 	 * PHYs.
3952 	 */
3953 
3954 	pmcs_free_phys(pwp, local_list);
3955 }
3956 
3957 /*
3958  * Top level routine to check expanders.  We call pmcs_check_expander for
3959  * each expander.  Since we're not doing any configuration right now, it
3960  * doesn't matter if this is breadth-first.
3961  */
3962 static void
3963 pmcs_check_expanders(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
3964 {
3965 	pmcs_phy_t *phyp, *pnext, *pchild;
3966 
3967 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
3968 	    "%s: %s", __func__, pptr->path);
3969 
3970 	/*
3971 	 * Check each expander at this level
3972 	 */
3973 	phyp = pptr;
3974 	while (phyp) {
3975 		pmcs_lock_phy(phyp);
3976 
3977 		if ((phyp->dtype == EXPANDER) && phyp->changed &&
3978 		    !phyp->dead && !phyp->subsidiary &&
3979 		    phyp->configured) {
3980 			pmcs_check_expander(pwp, phyp);
3981 		}
3982 
3983 		pnext = phyp->sibling;
3984 		pmcs_unlock_phy(phyp);
3985 		phyp = pnext;
3986 	}
3987 
3988 	/*
3989 	 * Now check the children
3990 	 */
3991 	phyp = pptr;
3992 	while (phyp) {
3993 		pmcs_lock_phy(phyp);
3994 		pnext = phyp->sibling;
3995 		pchild = phyp->children;
3996 		pmcs_unlock_phy(phyp);
3997 
3998 		if (pchild) {
3999 			pmcs_check_expanders(pwp, pchild);
4000 		}
4001 
4002 		phyp = pnext;
4003 	}
4004 }
4005 
4006 /*
4007  * Called with softstate and PHY locked
4008  */
4009 static void
4010 pmcs_clear_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr, int level)
4011 {
4012 	pmcs_phy_t *ctmp;
4013 
4014 	ASSERT(mutex_owned(&pwp->lock));
4015 	ASSERT(mutex_owned(&pptr->phy_lock));
4016 	ASSERT(pptr->level < PMCS_MAX_XPND - 1);
4017 
4018 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4019 	    "%s: checking %s", __func__, pptr->path);
4020 
4021 	ctmp = pptr->children;
4022 	while (ctmp) {
4023 		/*
4024 		 * If the expander is dead, mark its children dead
4025 		 */
4026 		if (pptr->dead) {
4027 			ctmp->dead = 1;
4028 		}
4029 		if (ctmp->dtype == EXPANDER) {
4030 			pmcs_clear_expander(pwp, ctmp, level + 1);
4031 		}
4032 		ctmp = ctmp->sibling;
4033 	}
4034 
4035 	/*
4036 	 * If this expander is not dead, we're done here.
4037 	 */
4038 	if (!pptr->dead) {
4039 		return;
4040 	}
4041 
4042 	/*
4043 	 * Now snip out the list of children below us and release them
4044 	 */
4045 	if (pptr->children) {
4046 		pmcs_add_dead_phys(pwp, pptr->children);
4047 	}
4048 
4049 	pptr->children = NULL;
4050 
4051 	/*
4052 	 * Clear subsidiary phys as well.  Getting the parent's PHY lock
4053 	 * is only necessary if level == 0 since otherwise the parent is
4054 	 * already locked.
4055 	 */
4056 	if (!IS_ROOT_PHY(pptr)) {
4057 		if (level == 0) {
4058 			mutex_enter(&pptr->parent->phy_lock);
4059 		}
4060 		ctmp = pptr->parent->children;
4061 		if (level == 0) {
4062 			mutex_exit(&pptr->parent->phy_lock);
4063 		}
4064 	} else {
4065 		ctmp = pwp->root_phys;
4066 	}
4067 
4068 	while (ctmp) {
4069 		if (ctmp == pptr) {
4070 			ctmp = ctmp->sibling;
4071 			continue;
4072 		}
4073 		/*
4074 		 * We only need to lock subsidiary PHYs on the level 0
4075 		 * expander.  Any children of that expander, subsidiaries or
4076 		 * not, will already be locked.
4077 		 */
4078 		if (level == 0) {
4079 			pmcs_lock_phy(ctmp);
4080 		}
4081 		if (ctmp->dtype != EXPANDER || ctmp->subsidiary == 0 ||
4082 		    memcmp(ctmp->sas_address, pptr->sas_address,
4083 		    sizeof (ctmp->sas_address)) != 0) {
4084 			if (level == 0) {
4085 				pmcs_unlock_phy(ctmp);
4086 			}
4087 			ctmp = ctmp->sibling;
4088 			continue;
4089 		}
4090 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
4091 		    "%s: subsidiary %s", __func__, ctmp->path);
4092 		pmcs_clear_phy(pwp, ctmp);
4093 		if (level == 0) {
4094 			pmcs_unlock_phy(ctmp);
4095 		}
4096 		ctmp = ctmp->sibling;
4097 	}
4098 
4099 	pmcs_clear_phy(pwp, pptr);
4100 }
4101 
4102 /*
4103  * Called with PHY locked and with scratch acquired. We return 0 if
4104  * we fail to allocate resources or notice that the configuration
4105  * count changed while we were running the command. We return
4106  * less than zero if we had an I/O error or received an unsupported
4107  * configuration. Otherwise we return the number of phys in the
4108  * expander.
4109  */
4110 #define	DFM(m, y) if (m == NULL) m = y
4111 static int
4112 pmcs_expander_get_nphy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4113 {
4114 	struct pmcwork *pwrk;
4115 	char buf[64];
4116 	const uint_t rdoff = 0x100;	/* returned data offset */
4117 	smp_response_frame_t *srf;
4118 	smp_report_general_resp_t *srgr;
4119 	uint32_t msg[PMCS_MSG_SIZE], *ptr, htag, status, ival;
4120 	int result = 0;
4121 
4122 	ival = 0x40001100;
4123 
4124 again:
4125 	if (!pptr->iport || !pptr->valid_device_id) {
4126 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4127 		    "%s: Can't reach PHY %s", __func__, pptr->path);
4128 		goto out;
4129 	}
4130 
4131 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4132 	if (pwrk == NULL) {
4133 		goto out;
4134 	}
4135 	(void) memset(pwp->scratch, 0x77, PMCS_SCRATCH_SIZE);
4136 	pwrk->arg = pwp->scratch;
4137 	pwrk->dtype = pptr->dtype;
4138 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4139 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4140 	if (ptr == NULL) {
4141 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4142 		pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, NULL,
4143 		    "%s: GET_IQ_ENTRY failed", __func__);
4144 		pmcs_pwork(pwp, pwrk);
4145 		goto out;
4146 	}
4147 
4148 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_SMP_REQUEST));
4149 	msg[1] = LE_32(pwrk->htag);
4150 	msg[2] = LE_32(pptr->device_id);
4151 	msg[3] = LE_32((4 << SMP_REQUEST_LENGTH_SHIFT) | SMP_INDIRECT_RESPONSE);
4152 	/*
4153 	 * Send SMP REPORT GENERAL (of either SAS1.1 or SAS2 flavors).
4154 	 */
4155 	msg[4] = BE_32(ival);
4156 	msg[5] = 0;
4157 	msg[6] = 0;
4158 	msg[7] = 0;
4159 	msg[8] = 0;
4160 	msg[9] = 0;
4161 	msg[10] = 0;
4162 	msg[11] = 0;
4163 	msg[12] = LE_32(DWORD0(pwp->scratch_dma+rdoff));
4164 	msg[13] = LE_32(DWORD1(pwp->scratch_dma+rdoff));
4165 	msg[14] = LE_32(PMCS_SCRATCH_SIZE - rdoff);
4166 	msg[15] = 0;
4167 
4168 	COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4169 
4170 	/* SMP serialization */
4171 	pmcs_smp_acquire(pptr->iport);
4172 
4173 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
4174 	htag = pwrk->htag;
4175 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4176 
4177 	pmcs_unlock_phy(pptr);
4178 	WAIT_FOR(pwrk, 1000, result);
4179 	/* Release SMP lock before reacquiring PHY lock */
4180 	pmcs_smp_release(pptr->iport);
4181 	pmcs_lock_phy(pptr);
4182 
4183 	pmcs_pwork(pwp, pwrk);
4184 
4185 	mutex_enter(&pwp->config_lock);
4186 	if (pwp->config_changed) {
4187 		RESTART_DISCOVERY_LOCKED(pwp);
4188 		mutex_exit(&pwp->config_lock);
4189 		result = 0;
4190 		goto out;
4191 	}
4192 	mutex_exit(&pwp->config_lock);
4193 
4194 	if (result) {
4195 		pmcs_timed_out(pwp, htag, __func__);
4196 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4197 		    "%s: Issuing SMP ABORT for htag 0x%08x", __func__, htag);
4198 		if (pmcs_abort(pwp, pptr, htag, 0, 0)) {
4199 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4200 			    "%s: Unable to issue SMP ABORT for htag 0x%08x",
4201 			    __func__, htag);
4202 		} else {
4203 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4204 			    "%s: Issuing SMP ABORT for htag 0x%08x",
4205 			    __func__, htag);
4206 		}
4207 		result = 0;
4208 		goto out;
4209 	}
4210 	ptr = (void *)pwp->scratch;
4211 	status = LE_32(ptr[2]);
4212 	if (status == PMCOUT_STATUS_UNDERFLOW ||
4213 	    status == PMCOUT_STATUS_OVERFLOW) {
4214 		pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW, pptr, NULL,
4215 		    "%s: over/underflow", __func__);
4216 		status = PMCOUT_STATUS_OK;
4217 	}
4218 	srf = (smp_response_frame_t *)&((uint32_t *)pwp->scratch)[rdoff >> 2];
4219 	srgr = (smp_report_general_resp_t *)
4220 	    &((uint32_t *)pwp->scratch)[(rdoff >> 2)+1];
4221 
4222 	if (status != PMCOUT_STATUS_OK) {
4223 		char *nag = NULL;
4224 		(void) snprintf(buf, sizeof (buf),
4225 		    "%s: SMP op failed (0x%x)", __func__, status);
4226 		switch (status) {
4227 		case PMCOUT_STATUS_IO_PORT_IN_RESET:
4228 			DFM(nag, "I/O Port In Reset");
4229 			/* FALLTHROUGH */
4230 		case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
4231 			DFM(nag, "Hardware Timeout");
4232 			/* FALLTHROUGH */
4233 		case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
4234 			DFM(nag, "Internal SMP Resource Failure");
4235 			/* FALLTHROUGH */
4236 		case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
4237 			DFM(nag, "PHY Not Ready");
4238 			/* FALLTHROUGH */
4239 		case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
4240 			DFM(nag, "Connection Rate Not Supported");
4241 			/* FALLTHROUGH */
4242 		case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
4243 			DFM(nag, "Open Retry Timeout");
4244 			/* FALLTHROUGH */
4245 		case PMCOUT_STATUS_IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
4246 			DFM(nag, "HW Resource Busy");
4247 			/* FALLTHROUGH */
4248 		case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
4249 			DFM(nag, "Response Connection Error");
4250 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4251 			    "%s: expander %s SMP operation failed (%s)",
4252 			    __func__, pptr->path, nag);
4253 			break;
4254 
4255 		/*
4256 		 * For the IO_DS_NON_OPERATIONAL case, we need to kick off
4257 		 * device state recovery and return 0 so that the caller
4258 		 * doesn't assume this expander is dead for good.
4259 		 */
4260 		case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL: {
4261 			pmcs_xscsi_t *xp = pptr->target;
4262 
4263 			pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, xp,
4264 			    "%s: expander %s device state non-operational",
4265 			    __func__, pptr->path);
4266 
4267 			if (xp == NULL) {
4268 				/*
4269 				 * Kick off recovery right now.
4270 				 */
4271 				SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
4272 				(void) ddi_taskq_dispatch(pwp->tq, pmcs_worker,
4273 				    pwp, DDI_NOSLEEP);
4274 			} else {
4275 				mutex_enter(&xp->statlock);
4276 				pmcs_start_dev_state_recovery(xp, pptr);
4277 				mutex_exit(&xp->statlock);
4278 			}
4279 
4280 			break;
4281 		}
4282 
4283 		default:
4284 			pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, ptr);
4285 			result = -EIO;
4286 			break;
4287 		}
4288 	} else if (srf->srf_frame_type != SMP_FRAME_TYPE_RESPONSE) {
4289 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4290 		    "%s: bad response frame type 0x%x",
4291 		    __func__, srf->srf_frame_type);
4292 		result = -EINVAL;
4293 	} else if (srf->srf_function != SMP_FUNC_REPORT_GENERAL) {
4294 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4295 		    "%s: bad response function 0x%x",
4296 		    __func__, srf->srf_function);
4297 		result = -EINVAL;
4298 	} else if (srf->srf_result != 0) {
4299 		/*
4300 		 * Check to see if we have a value of 3 for failure and
4301 		 * whether we were using a SAS2.0 allocation length value
4302 		 * and retry without it.
4303 		 */
4304 		if (srf->srf_result == 3 && (ival & 0xff00)) {
4305 			ival &= ~0xff00;
4306 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4307 			    "%s: err 0x%x with SAS2 request- retry with SAS1",
4308 			    __func__, srf->srf_result);
4309 			goto again;
4310 		}
4311 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4312 		    "%s: bad response 0x%x", __func__, srf->srf_result);
4313 		result = -EINVAL;
4314 	} else if (srgr->srgr_configuring) {
4315 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4316 		    "%s: expander at phy %s is still configuring",
4317 		    __func__, pptr->path);
4318 		result = 0;
4319 	} else {
4320 		result = srgr->srgr_number_of_phys;
4321 		if (ival & 0xff00) {
4322 			pptr->tolerates_sas2 = 1;
4323 		}
4324 		/*
4325 		 * Save off the REPORT_GENERAL response
4326 		 */
4327 		bcopy(srgr, &pptr->rg_resp, sizeof (smp_report_general_resp_t));
4328 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4329 		    "%s has %d phys and %s SAS2", pptr->path, result,
4330 		    pptr->tolerates_sas2? "tolerates" : "does not tolerate");
4331 	}
4332 out:
4333 	return (result);
4334 }
4335 
4336 /*
4337  * Called with expander locked (and thus, pptr) as well as all PHYs up to
4338  * the root, and scratch acquired. Return 0 if we fail to allocate resources
4339  * or notice that the configuration changed while we were running the command.
4340  *
4341  * We return less than zero if we had an I/O error or received an
4342  * unsupported configuration.
4343  */
4344 static int
4345 pmcs_expander_content_discover(pmcs_hw_t *pwp, pmcs_phy_t *expander,
4346     pmcs_phy_t *pptr)
4347 {
4348 	struct pmcwork *pwrk;
4349 	char buf[64];
4350 	uint8_t sas_address[8];
4351 	uint8_t att_sas_address[8];
4352 	smp_response_frame_t *srf;
4353 	smp_discover_resp_t *sdr;
4354 	const uint_t rdoff = 0x100;	/* returned data offset */
4355 	uint8_t *roff;
4356 	uint32_t status, *ptr, msg[PMCS_MSG_SIZE], htag;
4357 	int result = 0;
4358 	uint8_t	ini_support;
4359 	uint8_t	tgt_support;
4360 
4361 	if (!expander->iport || !expander->valid_device_id) {
4362 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, expander, expander->target,
4363 		    "%s: Can't reach PHY %s", __func__, expander->path);
4364 		goto out;
4365 	}
4366 
4367 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, expander);
4368 	if (pwrk == NULL) {
4369 		goto out;
4370 	}
4371 	(void) memset(pwp->scratch, 0x77, PMCS_SCRATCH_SIZE);
4372 	pwrk->arg = pwp->scratch;
4373 	pwrk->dtype = expander->dtype;
4374 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_SMP_REQUEST));
4375 	msg[1] = LE_32(pwrk->htag);
4376 	msg[2] = LE_32(expander->device_id);
4377 	msg[3] = LE_32((12 << SMP_REQUEST_LENGTH_SHIFT) |
4378 	    SMP_INDIRECT_RESPONSE);
4379 	/*
4380 	 * Send SMP DISCOVER (of either SAS1.1 or SAS2 flavors).
4381 	 */
4382 	if (expander->tolerates_sas2) {
4383 		msg[4] = BE_32(0x40101B00);
4384 	} else {
4385 		msg[4] = BE_32(0x40100000);
4386 	}
4387 	msg[5] = 0;
4388 	msg[6] = BE_32((pptr->phynum << 16));
4389 	msg[7] = 0;
4390 	msg[8] = 0;
4391 	msg[9] = 0;
4392 	msg[10] = 0;
4393 	msg[11] = 0;
4394 	msg[12] = LE_32(DWORD0(pwp->scratch_dma+rdoff));
4395 	msg[13] = LE_32(DWORD1(pwp->scratch_dma+rdoff));
4396 	msg[14] = LE_32(PMCS_SCRATCH_SIZE - rdoff);
4397 	msg[15] = 0;
4398 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4399 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4400 	if (ptr == NULL) {
4401 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4402 		goto out;
4403 	}
4404 
4405 	COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4406 
4407 	/* SMP serialization */
4408 	pmcs_smp_acquire(expander->iport);
4409 
4410 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
4411 	htag = pwrk->htag;
4412 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4413 
4414 	/*
4415 	 * Drop PHY lock while waiting so other completions aren't potentially
4416 	 * blocked.
4417 	 */
4418 	pmcs_unlock_phy(expander);
4419 	WAIT_FOR(pwrk, 1000, result);
4420 	/* Release SMP lock before reacquiring PHY lock */
4421 	pmcs_smp_release(expander->iport);
4422 	pmcs_lock_phy(expander);
4423 
4424 	pmcs_pwork(pwp, pwrk);
4425 
4426 	mutex_enter(&pwp->config_lock);
4427 	if (pwp->config_changed) {
4428 		RESTART_DISCOVERY_LOCKED(pwp);
4429 		mutex_exit(&pwp->config_lock);
4430 		result = 0;
4431 		goto out;
4432 	}
4433 	mutex_exit(&pwp->config_lock);
4434 
4435 	if (result) {
4436 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, pmcs_timeo, __func__);
4437 		if (pmcs_abort(pwp, expander, htag, 0, 0)) {
4438 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4439 			    "%s: Unable to issue SMP ABORT for htag 0x%08x",
4440 			    __func__, htag);
4441 		} else {
4442 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4443 			    "%s: Issuing SMP ABORT for htag 0x%08x",
4444 			    __func__, htag);
4445 		}
4446 		result = -ETIMEDOUT;
4447 		goto out;
4448 	}
4449 	ptr = (void *)pwp->scratch;
4450 	/*
4451 	 * Point roff to the DMA offset for returned data
4452 	 */
4453 	roff = pwp->scratch;
4454 	roff += rdoff;
4455 	srf = (smp_response_frame_t *)roff;
4456 	sdr = (smp_discover_resp_t *)(roff+4);
4457 	status = LE_32(ptr[2]);
4458 	if (status == PMCOUT_STATUS_UNDERFLOW ||
4459 	    status == PMCOUT_STATUS_OVERFLOW) {
4460 		pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW, pptr, NULL,
4461 		    "%s: over/underflow", __func__);
4462 		status = PMCOUT_STATUS_OK;
4463 	}
4464 	if (status != PMCOUT_STATUS_OK) {
4465 		char *nag = NULL;
4466 		(void) snprintf(buf, sizeof (buf),
4467 		    "%s: SMP op failed (0x%x)", __func__, status);
4468 		switch (status) {
4469 		case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
4470 			DFM(nag, "Hardware Timeout");
4471 			/* FALLTHROUGH */
4472 		case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
4473 			DFM(nag, "Internal SMP Resource Failure");
4474 			/* FALLTHROUGH */
4475 		case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
4476 			DFM(nag, "PHY Not Ready");
4477 			/* FALLTHROUGH */
4478 		case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
4479 			DFM(nag, "Connection Rate Not Supported");
4480 			/* FALLTHROUGH */
4481 		case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
4482 			DFM(nag, "Open Retry Timeout");
4483 			/* FALLTHROUGH */
4484 		case PMCOUT_STATUS_IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
4485 			DFM(nag, "HW Resource Busy");
4486 			/* FALLTHROUGH */
4487 		case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
4488 			DFM(nag, "Response Connection Error");
4489 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4490 			    "%s: expander %s SMP operation failed (%s)",
4491 			    __func__, pptr->path, nag);
4492 			break;
4493 		default:
4494 			pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, ptr);
4495 			result = -EIO;
4496 			break;
4497 		}
4498 		goto out;
4499 	} else if (srf->srf_frame_type != SMP_FRAME_TYPE_RESPONSE) {
4500 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4501 		    "%s: bad response frame type 0x%x",
4502 		    __func__, srf->srf_frame_type);
4503 		result = -EINVAL;
4504 		goto out;
4505 	} else if (srf->srf_function != SMP_FUNC_DISCOVER) {
4506 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4507 		    "%s: bad response function 0x%x",
4508 		    __func__, srf->srf_function);
4509 		result = -EINVAL;
4510 		goto out;
4511 	} else if (srf->srf_result != SMP_RES_FUNCTION_ACCEPTED) {
4512 		result = pmcs_smp_function_result(pwp, srf);
4513 		/* Need not fail if PHY is Vacant */
4514 		if (result != SMP_RES_PHY_VACANT) {
4515 			result = -EINVAL;
4516 			goto out;
4517 		}
4518 	}
4519 
4520 	/*
4521 	 * Save off the DISCOVER response
4522 	 */
4523 	bcopy(sdr, &pptr->disc_resp, sizeof (smp_discover_resp_t));
4524 
4525 	ini_support = (sdr->sdr_attached_sata_host |
4526 	    (sdr->sdr_attached_smp_initiator << 1) |
4527 	    (sdr->sdr_attached_stp_initiator << 2) |
4528 	    (sdr->sdr_attached_ssp_initiator << 3));
4529 
4530 	tgt_support = (sdr->sdr_attached_sata_device |
4531 	    (sdr->sdr_attached_smp_target << 1) |
4532 	    (sdr->sdr_attached_stp_target << 2) |
4533 	    (sdr->sdr_attached_ssp_target << 3));
4534 
4535 	pmcs_wwn2barray(BE_64(sdr->sdr_sas_addr), sas_address);
4536 	pmcs_wwn2barray(BE_64(sdr->sdr_attached_sas_addr), att_sas_address);
4537 
4538 	/*
4539 	 * Set the routing attribute regardless of the PHY type.
4540 	 */
4541 	pptr->routing_attr = sdr->sdr_routing_attr;
4542 
4543 	switch (sdr->sdr_attached_device_type) {
4544 	case SAS_IF_DTYPE_ENDPOINT:
4545 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4546 		    "exp_content: %s atdt=0x%x lr=%x is=%x ts=%x SAS="
4547 		    SAS_ADDR_FMT " attSAS=" SAS_ADDR_FMT " atPHY=%x",
4548 		    pptr->path,
4549 		    sdr->sdr_attached_device_type,
4550 		    sdr->sdr_negotiated_logical_link_rate,
4551 		    ini_support,
4552 		    tgt_support,
4553 		    SAS_ADDR_PRT(sas_address),
4554 		    SAS_ADDR_PRT(att_sas_address),
4555 		    sdr->sdr_attached_phy_identifier);
4556 
4557 		if (sdr->sdr_attached_sata_device ||
4558 		    sdr->sdr_attached_stp_target) {
4559 			pptr->dtype = SATA;
4560 		} else if (sdr->sdr_attached_ssp_target) {
4561 			pptr->dtype = SAS;
4562 		} else if (tgt_support || ini_support) {
4563 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4564 			    "%s: %s has tgt support=%x init support=(%x)",
4565 			    __func__, pptr->path, tgt_support, ini_support);
4566 		}
4567 
4568 		switch (pptr->routing_attr) {
4569 		case SMP_ROUTING_SUBTRACTIVE:
4570 		case SMP_ROUTING_TABLE:
4571 		case SMP_ROUTING_DIRECT:
4572 			pptr->routing_method = SMP_ROUTING_DIRECT;
4573 			break;
4574 		default:
4575 			pptr->routing_method = 0xff;	/* Invalid method */
4576 			break;
4577 		}
4578 		pmcs_update_phy_pm_props(pptr, (1ULL << pptr->phynum),
4579 		    (1ULL << sdr->sdr_attached_phy_identifier), B_TRUE);
4580 		break;
4581 	case SAS_IF_DTYPE_EDGE:
4582 	case SAS_IF_DTYPE_FANOUT:
4583 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4584 		    "exp_content: %s atdt=0x%x lr=%x is=%x ts=%x SAS="
4585 		    SAS_ADDR_FMT " attSAS=" SAS_ADDR_FMT " atPHY=%x",
4586 		    pptr->path,
4587 		    sdr->sdr_attached_device_type,
4588 		    sdr->sdr_negotiated_logical_link_rate,
4589 		    ini_support,
4590 		    tgt_support,
4591 		    SAS_ADDR_PRT(sas_address),
4592 		    SAS_ADDR_PRT(att_sas_address),
4593 		    sdr->sdr_attached_phy_identifier);
4594 		if (sdr->sdr_attached_smp_target) {
4595 			/*
4596 			 * Avoid configuring phys that just point back
4597 			 * at a parent phy
4598 			 */
4599 			if (expander->parent &&
4600 			    memcmp(expander->parent->sas_address,
4601 			    att_sas_address,
4602 			    sizeof (expander->parent->sas_address)) == 0) {
4603 				pmcs_prt(pwp, PMCS_PRT_DEBUG3, pptr, NULL,
4604 				    "%s: skipping port back to parent "
4605 				    "expander (%s)", __func__, pptr->path);
4606 				pptr->dtype = NOTHING;
4607 				break;
4608 			}
4609 			pptr->dtype = EXPANDER;
4610 
4611 		} else if (tgt_support || ini_support) {
4612 			pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4613 			    "%s has tgt support=%x init support=(%x)",
4614 			    pptr->path, tgt_support, ini_support);
4615 			pptr->dtype = EXPANDER;
4616 		}
4617 		if (pptr->routing_attr == SMP_ROUTING_DIRECT) {
4618 			pptr->routing_method = 0xff;	/* Invalid method */
4619 		} else {
4620 			pptr->routing_method = pptr->routing_attr;
4621 		}
4622 		pmcs_update_phy_pm_props(pptr, (1ULL << pptr->phynum),
4623 		    (1ULL << sdr->sdr_attached_phy_identifier), B_TRUE);
4624 		break;
4625 	default:
4626 		pptr->dtype = NOTHING;
4627 		break;
4628 	}
4629 	if (pptr->dtype != NOTHING) {
4630 		pmcs_phy_t *ctmp;
4631 
4632 		/*
4633 		 * If the attached device is a SATA device and the expander
4634 		 * is (possibly) a SAS2 compliant expander, check for whether
4635 		 * there is a NAA=5 WWN field starting at this offset and
4636 		 * use that for the SAS Address for this device.
4637 		 */
4638 		if (expander->tolerates_sas2 && pptr->dtype == SATA &&
4639 		    (roff[SAS_ATTACHED_NAME_OFFSET] >> 8) == NAA_IEEE_REG) {
4640 			(void) memcpy(pptr->sas_address,
4641 			    &roff[SAS_ATTACHED_NAME_OFFSET], 8);
4642 		} else {
4643 			(void) memcpy(pptr->sas_address, att_sas_address, 8);
4644 		}
4645 		pptr->atdt = (sdr->sdr_attached_device_type);
4646 		/*
4647 		 * Now run up from the expander's parent up to the top to
4648 		 * make sure we only use the least common link_rate.
4649 		 */
4650 		for (ctmp = expander->parent; ctmp; ctmp = ctmp->parent) {
4651 			if (ctmp->link_rate <
4652 			    sdr->sdr_negotiated_logical_link_rate) {
4653 				pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL,
4654 				    "%s: derating link rate from %x to %x due "
4655 				    "to %s being slower", pptr->path,
4656 				    sdr->sdr_negotiated_logical_link_rate,
4657 				    ctmp->link_rate,
4658 				    ctmp->path);
4659 				sdr->sdr_negotiated_logical_link_rate =
4660 				    ctmp->link_rate;
4661 			}
4662 		}
4663 		pptr->link_rate = sdr->sdr_negotiated_logical_link_rate;
4664 		pptr->state.prog_min_rate = sdr->sdr_prog_min_phys_link_rate;
4665 		pptr->state.hw_min_rate = sdr->sdr_hw_min_phys_link_rate;
4666 		pptr->state.prog_max_rate = sdr->sdr_prog_max_phys_link_rate;
4667 		pptr->state.hw_max_rate = sdr->sdr_hw_max_phys_link_rate;
4668 		PHY_CHANGED(pwp, pptr);
4669 	} else {
4670 		pmcs_clear_phy(pwp, pptr);
4671 	}
4672 	result = 1;
4673 out:
4674 	return (result);
4675 }
4676 
4677 /*
4678  * Get a work structure and assign it a tag with type and serial number
4679  * If a structure is returned, it is returned locked.
4680  */
4681 pmcwork_t *
4682 pmcs_gwork(pmcs_hw_t *pwp, uint32_t tag_type, pmcs_phy_t *phyp)
4683 {
4684 	pmcwork_t *p;
4685 	uint16_t snum;
4686 	uint32_t off;
4687 
4688 	mutex_enter(&pwp->wfree_lock);
4689 	p = STAILQ_FIRST(&pwp->wf);
4690 	if (p == NULL) {
4691 		/*
4692 		 * If we couldn't get a work structure, it's time to bite
4693 		 * the bullet, grab the pfree_lock and copy over all the
4694 		 * work structures from the pending free list to the actual
4695 		 * free list (assuming it's not also empty).
4696 		 */
4697 		mutex_enter(&pwp->pfree_lock);
4698 		if (STAILQ_FIRST(&pwp->pf) == NULL) {
4699 			mutex_exit(&pwp->pfree_lock);
4700 			mutex_exit(&pwp->wfree_lock);
4701 			return (NULL);
4702 		}
4703 		pwp->wf.stqh_first = pwp->pf.stqh_first;
4704 		pwp->wf.stqh_last = pwp->pf.stqh_last;
4705 		STAILQ_INIT(&pwp->pf);
4706 		mutex_exit(&pwp->pfree_lock);
4707 
4708 		p = STAILQ_FIRST(&pwp->wf);
4709 		ASSERT(p != NULL);
4710 	}
4711 	STAILQ_REMOVE(&pwp->wf, p, pmcwork, next);
4712 	snum = pwp->wserno++;
4713 	mutex_exit(&pwp->wfree_lock);
4714 
4715 	off = p - pwp->work;
4716 
4717 	mutex_enter(&p->lock);
4718 	ASSERT(p->state == PMCS_WORK_STATE_NIL);
4719 	ASSERT(p->htag == PMCS_TAG_FREE);
4720 	p->htag = (tag_type << PMCS_TAG_TYPE_SHIFT) & PMCS_TAG_TYPE_MASK;
4721 	p->htag |= ((snum << PMCS_TAG_SERNO_SHIFT) & PMCS_TAG_SERNO_MASK);
4722 	p->htag |= ((off << PMCS_TAG_INDEX_SHIFT) & PMCS_TAG_INDEX_MASK);
4723 	p->start = gethrtime();
4724 	p->state = PMCS_WORK_STATE_READY;
4725 	p->ssp_event = 0;
4726 	p->dead = 0;
4727 
4728 	if (phyp) {
4729 		p->phy = phyp;
4730 		pmcs_inc_phy_ref_count(phyp);
4731 	}
4732 
4733 	return (p);
4734 }
4735 
4736 /*
4737  * Called with pwrk lock held.  Returned with lock released.
4738  */
4739 void
4740 pmcs_pwork(pmcs_hw_t *pwp, pmcwork_t *p)
4741 {
4742 	ASSERT(p != NULL);
4743 	ASSERT(mutex_owned(&p->lock));
4744 
4745 	p->last_ptr = p->ptr;
4746 	p->last_arg = p->arg;
4747 	p->last_phy = p->phy;
4748 	p->last_xp = p->xp;
4749 	p->last_htag = p->htag;
4750 	p->last_state = p->state;
4751 	p->finish = gethrtime();
4752 
4753 	if (p->phy) {
4754 		pmcs_dec_phy_ref_count(p->phy);
4755 	}
4756 
4757 	p->state = PMCS_WORK_STATE_NIL;
4758 	p->htag = PMCS_TAG_FREE;
4759 	p->xp = NULL;
4760 	p->ptr = NULL;
4761 	p->arg = NULL;
4762 	p->phy = NULL;
4763 	p->abt_htag = 0;
4764 	p->timer = 0;
4765 	mutex_exit(&p->lock);
4766 
4767 	if (mutex_tryenter(&pwp->wfree_lock) == 0) {
4768 		mutex_enter(&pwp->pfree_lock);
4769 		STAILQ_INSERT_TAIL(&pwp->pf, p, next);
4770 		mutex_exit(&pwp->pfree_lock);
4771 	} else {
4772 		STAILQ_INSERT_TAIL(&pwp->wf, p, next);
4773 		mutex_exit(&pwp->wfree_lock);
4774 	}
4775 }
4776 
4777 /*
4778  * Find a work structure based upon a tag and make sure that the tag
4779  * serial number matches the work structure we've found.
4780  * If a structure is found, its lock is held upon return.
4781  */
4782 pmcwork_t *
4783 pmcs_tag2wp(pmcs_hw_t *pwp, uint32_t htag)
4784 {
4785 	pmcwork_t *p;
4786 	uint32_t idx = PMCS_TAG_INDEX(htag);
4787 
4788 	p = &pwp->work[idx];
4789 
4790 	mutex_enter(&p->lock);
4791 	if (p->htag == htag) {
4792 		return (p);
4793 	}
4794 	mutex_exit(&p->lock);
4795 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
4796 	    "INDEX 0x%x HTAG 0x%x got p->htag 0x%x", idx, htag, p->htag);
4797 	return (NULL);
4798 }
4799 
4800 /*
4801  * Issue an abort for a command or for all commands.
4802  *
4803  * Since this can be called from interrupt context,
4804  * we don't wait for completion if wait is not set.
4805  *
4806  * Called with PHY lock held.
4807  */
4808 int
4809 pmcs_abort(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint32_t tag, int all_cmds,
4810     int wait)
4811 {
4812 	pmcwork_t *pwrk;
4813 	pmcs_xscsi_t *tgt;
4814 	uint32_t msg[PMCS_MSG_SIZE], *ptr;
4815 	int result, abt_type;
4816 	uint32_t abt_htag, status;
4817 
4818 	if (pptr->abort_all_start) {
4819 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: ABORT_ALL for "
4820 		    "(%s) already in progress.", __func__, pptr->path);
4821 		return (EBUSY);
4822 	}
4823 
4824 	switch (pptr->dtype) {
4825 	case SAS:
4826 		abt_type = PMCIN_SSP_ABORT;
4827 		break;
4828 	case SATA:
4829 		abt_type = PMCIN_SATA_ABORT;
4830 		break;
4831 	case EXPANDER:
4832 		abt_type = PMCIN_SMP_ABORT;
4833 		break;
4834 	default:
4835 		return (0);
4836 	}
4837 
4838 	pwrk = pmcs_gwork(pwp, wait ? PMCS_TAG_TYPE_WAIT : PMCS_TAG_TYPE_NONE,
4839 	    pptr);
4840 
4841 	if (pwrk == NULL) {
4842 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
4843 		return (ENOMEM);
4844 	}
4845 
4846 	pwrk->dtype = pptr->dtype;
4847 	if (wait) {
4848 		pwrk->arg = msg;
4849 	}
4850 	if (pptr->valid_device_id == 0) {
4851 		pmcs_pwork(pwp, pwrk);
4852 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4853 		    "%s: Invalid DeviceID", __func__);
4854 		return (ENODEV);
4855 	}
4856 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, abt_type));
4857 	msg[1] = LE_32(pwrk->htag);
4858 	msg[2] = LE_32(pptr->device_id);
4859 	if (all_cmds) {
4860 		msg[3] = 0;
4861 		msg[4] = LE_32(1);
4862 		pwrk->ptr = NULL;
4863 		pptr->abort_all_start = gethrtime();
4864 	} else {
4865 		msg[3] = LE_32(tag);
4866 		msg[4] = 0;
4867 		pwrk->abt_htag = tag;
4868 	}
4869 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4870 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4871 	if (ptr == NULL) {
4872 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4873 		pmcs_pwork(pwp, pwrk);
4874 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
4875 		return (ENOMEM);
4876 	}
4877 
4878 	COPY_MESSAGE(ptr, msg, 5);
4879 	if (all_cmds) {
4880 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4881 		    "%s: aborting all commands for %s device %s. (htag=0x%x)",
4882 		    __func__, pmcs_get_typename(pptr->dtype), pptr->path,
4883 		    msg[1]);
4884 	} else {
4885 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4886 		    "%s: aborting tag 0x%x for %s device %s. (htag=0x%x)",
4887 		    __func__, tag, pmcs_get_typename(pptr->dtype), pptr->path,
4888 		    msg[1]);
4889 	}
4890 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
4891 
4892 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4893 	if (!wait) {
4894 		mutex_exit(&pwrk->lock);
4895 		return (0);
4896 	}
4897 
4898 	abt_htag = pwrk->htag;
4899 	pmcs_unlock_phy(pwrk->phy);
4900 	WAIT_FOR(pwrk, 1000, result);
4901 	pmcs_lock_phy(pwrk->phy);
4902 
4903 	tgt = pwrk->xp;
4904 	pmcs_pwork(pwp, pwrk);
4905 
4906 	if (tgt != NULL) {
4907 		mutex_enter(&tgt->aqlock);
4908 		if (!STAILQ_EMPTY(&tgt->aq)) {
4909 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4910 			    "%s: Abort complete (result=0x%x), but "
4911 			    "aq not empty (tgt 0x%p), waiting",
4912 			    __func__, result, (void *)tgt);
4913 			cv_wait(&tgt->abort_cv, &tgt->aqlock);
4914 		}
4915 		mutex_exit(&tgt->aqlock);
4916 	}
4917 
4918 	if (all_cmds) {
4919 		pptr->abort_all_start = 0;
4920 		cv_signal(&pptr->abort_all_cv);
4921 	}
4922 
4923 	if (result) {
4924 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4925 		    "%s: Abort (htag 0x%08x) request timed out",
4926 		    __func__, abt_htag);
4927 		if (tgt != NULL) {
4928 			mutex_enter(&tgt->statlock);
4929 			if ((tgt->dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) &&
4930 			    (tgt->dev_state !=
4931 			    PMCS_DEVICE_STATE_NON_OPERATIONAL)) {
4932 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4933 				    "%s: Trying DS error recovery for tgt 0x%p",
4934 				    __func__, (void *)tgt);
4935 				(void) pmcs_send_err_recovery_cmd(pwp,
4936 				    PMCS_DEVICE_STATE_IN_RECOVERY, pptr, tgt);
4937 			}
4938 			mutex_exit(&tgt->statlock);
4939 		}
4940 		return (ETIMEDOUT);
4941 	}
4942 
4943 	status = LE_32(msg[2]);
4944 	if (status != PMCOUT_STATUS_OK) {
4945 		/*
4946 		 * The only non-success status are IO_NOT_VALID &
4947 		 * IO_ABORT_IN_PROGRESS.
4948 		 * In case of IO_ABORT_IN_PROGRESS, the other ABORT cmd's
4949 		 * status is of concern and this duplicate cmd status can
4950 		 * be ignored.
4951 		 * If IO_NOT_VALID, that's not an error per-se.
4952 		 * For abort of single I/O complete the command anyway.
4953 		 * If, however, we were aborting all, that is a problem
4954 		 * as IO_NOT_VALID really means that the IO or device is
4955 		 * not there. So, discovery process will take of the cleanup.
4956 		 */
4957 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4958 		    "%s: abort result 0x%x", __func__, LE_32(msg[2]));
4959 		if (all_cmds) {
4960 			PHY_CHANGED(pwp, pptr);
4961 			RESTART_DISCOVERY(pwp);
4962 		} else {
4963 			return (EINVAL);
4964 		}
4965 
4966 		return (0);
4967 	}
4968 
4969 	if (tgt != NULL) {
4970 		mutex_enter(&tgt->statlock);
4971 		if (tgt->dev_state == PMCS_DEVICE_STATE_IN_RECOVERY) {
4972 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
4973 			    "%s: Restoring OPERATIONAL dev_state for tgt 0x%p",
4974 			    __func__, (void *)tgt);
4975 			(void) pmcs_send_err_recovery_cmd(pwp,
4976 			    PMCS_DEVICE_STATE_OPERATIONAL, pptr, tgt);
4977 		}
4978 		mutex_exit(&tgt->statlock);
4979 	}
4980 
4981 	return (0);
4982 }
4983 
4984 /*
4985  * Issue a task management function to an SSP device.
4986  *
4987  * Called with PHY lock held.
4988  * statlock CANNOT be held upon entry.
4989  */
4990 int
4991 pmcs_ssp_tmf(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint8_t tmf, uint32_t tag,
4992     uint64_t lun, uint32_t *response)
4993 {
4994 	int result, ds;
4995 	uint8_t local[PMCS_QENTRY_SIZE << 1], *xd;
4996 	sas_ssp_rsp_iu_t *rptr = (void *)local;
4997 	static const uint8_t ssp_rsp_evec[] = {
4998 		0x58, 0x61, 0x56, 0x72, 0x00
4999 	};
5000 	uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
5001 	struct pmcwork *pwrk;
5002 	pmcs_xscsi_t *xp;
5003 
5004 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
5005 	if (pwrk == NULL) {
5006 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
5007 		return (ENOMEM);
5008 	}
5009 	/*
5010 	 * NB: We use the PMCS_OQ_GENERAL outbound queue
5011 	 * NB: so as to not get entangled in normal I/O
5012 	 * NB: processing.
5013 	 */
5014 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
5015 	    PMCIN_SSP_INI_TM_START));
5016 	msg[1] = LE_32(pwrk->htag);
5017 	msg[2] = LE_32(pptr->device_id);
5018 	if (tmf == SAS_ABORT_TASK || tmf == SAS_QUERY_TASK) {
5019 		msg[3] = LE_32(tag);
5020 	} else {
5021 		msg[3] = 0;
5022 	}
5023 	msg[4] = LE_32(tmf);
5024 	msg[5] = BE_32((uint32_t)lun);
5025 	msg[6] = BE_32((uint32_t)(lun >> 32));
5026 	msg[7] = LE_32(PMCIN_MESSAGE_REPORT);
5027 
5028 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5029 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5030 	if (ptr == NULL) {
5031 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5032 		pmcs_pwork(pwp, pwrk);
5033 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
5034 		return (ENOMEM);
5035 	}
5036 	COPY_MESSAGE(ptr, msg, 7);
5037 	pwrk->arg = msg;
5038 	pwrk->dtype = pptr->dtype;
5039 	xp = pptr->target;
5040 	pwrk->xp = xp;
5041 
5042 	if (xp != NULL) {
5043 		mutex_enter(&xp->statlock);
5044 		if (xp->dev_state == PMCS_DEVICE_STATE_NON_OPERATIONAL) {
5045 			mutex_exit(&xp->statlock);
5046 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5047 			pmcs_pwork(pwp, pwrk);
5048 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, "%s: Not "
5049 			    "sending '%s' because DS is '%s'", __func__,
5050 			    pmcs_tmf2str(tmf), pmcs_status_str
5051 			    (PMCOUT_STATUS_IO_DS_NON_OPERATIONAL));
5052 			return (EIO);
5053 		}
5054 		mutex_exit(&xp->statlock);
5055 	}
5056 
5057 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5058 	    "%s: sending '%s' to %s (lun %llu) tag 0x%x", __func__,
5059 	    pmcs_tmf2str(tmf), pptr->path, (unsigned long long) lun, tag);
5060 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
5061 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5062 
5063 	pmcs_unlock_phy(pptr);
5064 	/*
5065 	 * This is a command sent to the target device, so it can take
5066 	 * significant amount of time to complete when path & device is busy.
5067 	 * Set a timeout to 20 seconds
5068 	 */
5069 	WAIT_FOR(pwrk, 20000, result);
5070 	pmcs_lock_phy(pptr);
5071 	pmcs_pwork(pwp, pwrk);
5072 
5073 	if (result) {
5074 		if (xp == NULL) {
5075 			return (ETIMEDOUT);
5076 		}
5077 
5078 		mutex_enter(&xp->statlock);
5079 		pmcs_start_dev_state_recovery(xp, pptr);
5080 		mutex_exit(&xp->statlock);
5081 		return (ETIMEDOUT);
5082 	}
5083 
5084 	status = LE_32(msg[2]);
5085 	if (status != PMCOUT_STATUS_OK) {
5086 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5087 		    "%s: status %s for TMF %s action to %s, lun %llu",
5088 		    __func__, pmcs_status_str(status),  pmcs_tmf2str(tmf),
5089 		    pptr->path, (unsigned long long) lun);
5090 		if ((status == PMCOUT_STATUS_IO_DS_NON_OPERATIONAL) ||
5091 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK) ||
5092 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS)) {
5093 			ds = PMCS_DEVICE_STATE_NON_OPERATIONAL;
5094 		} else if (status == PMCOUT_STATUS_IO_DS_IN_RECOVERY) {
5095 			/*
5096 			 * If the status is IN_RECOVERY, it's an indication
5097 			 * that it's now time for us to request to have the
5098 			 * device state set to OPERATIONAL since we're the ones
5099 			 * that requested recovery to begin with.
5100 			 */
5101 			ds = PMCS_DEVICE_STATE_OPERATIONAL;
5102 		} else {
5103 			ds = PMCS_DEVICE_STATE_IN_RECOVERY;
5104 		}
5105 		if (xp != NULL) {
5106 			mutex_enter(&xp->statlock);
5107 			if (xp->dev_state != ds) {
5108 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5109 				    "%s: Sending err recovery cmd"
5110 				    " for tgt 0x%p (status = %s)",
5111 				    __func__, (void *)xp,
5112 				    pmcs_status_str(status));
5113 				(void) pmcs_send_err_recovery_cmd(pwp, ds,
5114 				    pptr, xp);
5115 			}
5116 			mutex_exit(&xp->statlock);
5117 		}
5118 		return (EIO);
5119 	} else {
5120 		ds = PMCS_DEVICE_STATE_OPERATIONAL;
5121 		if (xp != NULL) {
5122 			mutex_enter(&xp->statlock);
5123 			if (xp->dev_state != ds) {
5124 				pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5125 				    "%s: Sending err recovery cmd"
5126 				    " for tgt 0x%p (status = %s)",
5127 				    __func__, (void *)xp,
5128 				    pmcs_status_str(status));
5129 				(void) pmcs_send_err_recovery_cmd(pwp, ds,
5130 				    pptr, xp);
5131 			}
5132 			mutex_exit(&xp->statlock);
5133 		}
5134 	}
5135 	if (LE_32(msg[3]) == 0) {
5136 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5137 		    "TMF completed with no response");
5138 		return (EIO);
5139 	}
5140 	pmcs_endian_transform(pwp, local, &msg[5], ssp_rsp_evec);
5141 	xd = (uint8_t *)(&msg[5]);
5142 	xd += SAS_RSP_HDR_SIZE;
5143 	if (rptr->datapres != SAS_RSP_DATAPRES_RESPONSE_DATA) {
5144 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5145 		    "%s: TMF response not RESPONSE DATA (0x%x)",
5146 		    __func__, rptr->datapres);
5147 		return (EIO);
5148 	}
5149 	if (rptr->response_data_length != 4) {
5150 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
5151 		    "Bad SAS RESPONSE DATA LENGTH", msg);
5152 		return (EIO);
5153 	}
5154 	(void) memcpy(&status, xd, sizeof (uint32_t));
5155 	status = BE_32(status);
5156 	if (response != NULL)
5157 		*response = status;
5158 	/*
5159 	 * The status is actually in the low-order byte.  The upper three
5160 	 * bytes contain additional information for the TMFs that support them.
5161 	 * However, at this time we do not issue any of those.  In the other
5162 	 * cases, the upper three bytes are supposed to be 0, but it appears
5163 	 * they aren't always.  Just mask them off.
5164 	 */
5165 	switch (status & 0xff) {
5166 	case SAS_RSP_TMF_COMPLETE:
5167 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5168 		    "%s: TMF complete", __func__);
5169 		result = 0;
5170 		break;
5171 	case SAS_RSP_TMF_SUCCEEDED:
5172 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5173 		    "%s: TMF succeeded", __func__);
5174 		result = 0;
5175 		break;
5176 	case SAS_RSP_INVALID_FRAME:
5177 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5178 		    "%s: TMF returned INVALID FRAME", __func__);
5179 		result = EIO;
5180 		break;
5181 	case SAS_RSP_TMF_NOT_SUPPORTED:
5182 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5183 		    "%s: TMF returned TMF NOT SUPPORTED", __func__);
5184 		result = EIO;
5185 		break;
5186 	case SAS_RSP_TMF_FAILED:
5187 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5188 		    "%s: TMF returned TMF FAILED", __func__);
5189 		result = EIO;
5190 		break;
5191 	case SAS_RSP_TMF_INCORRECT_LUN:
5192 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5193 		    "%s: TMF returned INCORRECT LUN", __func__);
5194 		result = EIO;
5195 		break;
5196 	case SAS_RSP_OVERLAPPED_OIPTTA:
5197 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5198 		    "%s: TMF returned OVERLAPPED INITIATOR PORT TRANSFER TAG "
5199 		    "ATTEMPTED", __func__);
5200 		result = EIO;
5201 		break;
5202 	default:
5203 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
5204 		    "%s: TMF returned unknown code 0x%x", __func__, status);
5205 		result = EIO;
5206 		break;
5207 	}
5208 	return (result);
5209 }
5210 
5211 /*
5212  * Called with PHY lock held and scratch acquired
5213  */
5214 int
5215 pmcs_sata_abort_ncq(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
5216 {
5217 	const char *utag_fail_fmt = "%s: untagged NCQ command failure";
5218 	const char *tag_fail_fmt = "%s: NCQ command failure (tag 0x%x)";
5219 	uint32_t msg[PMCS_QENTRY_SIZE], *ptr, result, status;
5220 	uint8_t *fp = pwp->scratch, ds;
5221 	fis_t fis;
5222 	pmcwork_t *pwrk;
5223 	pmcs_xscsi_t *tgt;
5224 
5225 	pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
5226 	if (pwrk == NULL) {
5227 		return (ENOMEM);
5228 	}
5229 	msg[0] = LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE,
5230 	    PMCIN_SATA_HOST_IO_START));
5231 	msg[1] = LE_32(pwrk->htag);
5232 	msg[2] = LE_32(pptr->device_id);
5233 	msg[3] = LE_32(512);
5234 	msg[4] = LE_32(SATA_PROTOCOL_PIO | PMCIN_DATADIR_2_INI);
5235 	msg[5] = LE_32((READ_LOG_EXT << 16) | (C_BIT << 8) | FIS_REG_H2DEV);
5236 	msg[6] = LE_32(0x10);
5237 	msg[8] = LE_32(1);
5238 	msg[9] = 0;
5239 	msg[10] = 0;
5240 	msg[11] = 0;
5241 	msg[12] = LE_32(DWORD0(pwp->scratch_dma));
5242 	msg[13] = LE_32(DWORD1(pwp->scratch_dma));
5243 	msg[14] = LE_32(512);
5244 	msg[15] = 0;
5245 
5246 	pwrk->arg = msg;
5247 	pwrk->dtype = pptr->dtype;
5248 
5249 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5250 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5251 	if (ptr == NULL) {
5252 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5253 		pmcs_pwork(pwp, pwrk);
5254 		return (ENOMEM);
5255 	}
5256 	COPY_MESSAGE(ptr, msg, PMCS_QENTRY_SIZE);
5257 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
5258 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5259 
5260 	pmcs_unlock_phy(pptr);
5261 	WAIT_FOR(pwrk, 250, result);
5262 	pmcs_lock_phy(pptr);
5263 	pmcs_pwork(pwp, pwrk);
5264 
5265 	tgt = pptr->target;
5266 	if (result) {
5267 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt, pmcs_timeo, __func__);
5268 		return (EIO);
5269 	}
5270 	status = LE_32(msg[2]);
5271 	if (status != PMCOUT_STATUS_OK || LE_32(msg[3])) {
5272 		if (tgt == NULL) {
5273 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
5274 			    "%s: cannot find target for phy 0x%p for "
5275 			    "dev state recovery", __func__, (void *)pptr);
5276 			return (EIO);
5277 		}
5278 
5279 		mutex_enter(&tgt->statlock);
5280 
5281 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG, "READ LOG EXT", msg);
5282 		if ((status == PMCOUT_STATUS_IO_DS_NON_OPERATIONAL) ||
5283 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK) ||
5284 		    (status == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS)) {
5285 			ds = PMCS_DEVICE_STATE_NON_OPERATIONAL;
5286 		} else {
5287 			ds = PMCS_DEVICE_STATE_IN_RECOVERY;
5288 		}
5289 		if (tgt->dev_state != ds) {
5290 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt, "%s: Trying "
5291 			    "SATA DS Recovery for tgt(0x%p) for status(%s)",
5292 			    __func__, (void *)tgt, pmcs_status_str(status));
5293 			(void) pmcs_send_err_recovery_cmd(pwp, ds, pptr, tgt);
5294 		}
5295 
5296 		mutex_exit(&tgt->statlock);
5297 		return (EIO);
5298 	}
5299 	fis[0] = (fp[4] << 24) | (fp[3] << 16) | (fp[2] << 8) | FIS_REG_D2H;
5300 	fis[1] = (fp[8] << 24) | (fp[7] << 16) | (fp[6] << 8) | fp[5];
5301 	fis[2] = (fp[12] << 24) | (fp[11] << 16) | (fp[10] << 8) | fp[9];
5302 	fis[3] = (fp[16] << 24) | (fp[15] << 16) | (fp[14] << 8) | fp[13];
5303 	fis[4] = 0;
5304 	if (fp[0] & 0x80) {
5305 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
5306 		    utag_fail_fmt, __func__);
5307 	} else {
5308 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
5309 		    tag_fail_fmt, __func__, fp[0] & 0x1f);
5310 	}
5311 	pmcs_fis_dump(pwp, fis);
5312 	pptr->need_rl_ext = 0;
5313 	return (0);
5314 }
5315 
5316 /*
5317  * Transform a structure from CPU to Device endian format, or
5318  * vice versa, based upon a transformation vector.
5319  *
5320  * A transformation vector is an array of bytes, each byte
5321  * of which is defined thusly:
5322  *
5323  *  bit 7: from CPU to desired endian, otherwise from desired endian
5324  *	   to CPU format
5325  *  bit 6: Big Endian, else Little Endian
5326  *  bits 5-4:
5327  *       00 Undefined
5328  *       01 One Byte quantities
5329  *       02 Two Byte quantities
5330  *       03 Four Byte quantities
5331  *
5332  *  bits 3-0:
5333  *       00 Undefined
5334  *       Number of quantities to transform
5335  *
5336  * The vector is terminated by a 0 value.
5337  */
5338 
5339 void
5340 pmcs_endian_transform(pmcs_hw_t *pwp, void *orig_out, void *orig_in,
5341     const uint8_t *xfvec)
5342 {
5343 	uint8_t c, *out = orig_out, *in = orig_in;
5344 
5345 	if (xfvec == NULL) {
5346 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
5347 		    "%s: null xfvec", __func__);
5348 		return;
5349 	}
5350 	if (out == NULL) {
5351 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
5352 		    "%s: null out", __func__);
5353 		return;
5354 	}
5355 	if (in == NULL) {
5356 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
5357 		    "%s: null in", __func__);
5358 		return;
5359 	}
5360 	while ((c = *xfvec++) != 0) {
5361 		int nbyt = (c & 0xf);
5362 		int size = (c >> 4) & 0x3;
5363 		int bige = (c >> 4) & 0x4;
5364 
5365 		switch (size) {
5366 		case 1:
5367 		{
5368 			while (nbyt-- > 0) {
5369 				*out++ = *in++;
5370 			}
5371 			break;
5372 		}
5373 		case 2:
5374 		{
5375 			uint16_t tmp;
5376 			while (nbyt-- > 0) {
5377 				(void) memcpy(&tmp, in, sizeof (uint16_t));
5378 				if (bige) {
5379 					tmp = BE_16(tmp);
5380 				} else {
5381 					tmp = LE_16(tmp);
5382 				}
5383 				(void) memcpy(out, &tmp, sizeof (uint16_t));
5384 				out += sizeof (uint16_t);
5385 				in += sizeof (uint16_t);
5386 			}
5387 			break;
5388 		}
5389 		case 3:
5390 		{
5391 			uint32_t tmp;
5392 			while (nbyt-- > 0) {
5393 				(void) memcpy(&tmp, in, sizeof (uint32_t));
5394 				if (bige) {
5395 					tmp = BE_32(tmp);
5396 				} else {
5397 					tmp = LE_32(tmp);
5398 				}
5399 				(void) memcpy(out, &tmp, sizeof (uint32_t));
5400 				out += sizeof (uint32_t);
5401 				in += sizeof (uint32_t);
5402 			}
5403 			break;
5404 		}
5405 		default:
5406 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
5407 			    "%s: bad size", __func__);
5408 			return;
5409 		}
5410 	}
5411 }
5412 
5413 const char *
5414 pmcs_get_rate(unsigned int linkrt)
5415 {
5416 	const char *rate;
5417 	switch (linkrt) {
5418 	case SAS_LINK_RATE_1_5GBIT:
5419 		rate = "1.5";
5420 		break;
5421 	case SAS_LINK_RATE_3GBIT:
5422 		rate = "3.0";
5423 		break;
5424 	case SAS_LINK_RATE_6GBIT:
5425 		rate = "6.0";
5426 		break;
5427 	default:
5428 		rate = "???";
5429 		break;
5430 	}
5431 	return (rate);
5432 }
5433 
5434 const char *
5435 pmcs_get_typename(pmcs_dtype_t type)
5436 {
5437 	switch (type) {
5438 	case NOTHING:
5439 		return ("NIL");
5440 	case SATA:
5441 		return ("SATA");
5442 	case SAS:
5443 		return ("SSP");
5444 	case EXPANDER:
5445 		return ("EXPANDER");
5446 	}
5447 	return ("????");
5448 }
5449 
5450 const char *
5451 pmcs_tmf2str(int tmf)
5452 {
5453 	switch (tmf) {
5454 	case SAS_ABORT_TASK:
5455 		return ("Abort Task");
5456 	case SAS_ABORT_TASK_SET:
5457 		return ("Abort Task Set");
5458 	case SAS_CLEAR_TASK_SET:
5459 		return ("Clear Task Set");
5460 	case SAS_LOGICAL_UNIT_RESET:
5461 		return ("Logical Unit Reset");
5462 	case SAS_I_T_NEXUS_RESET:
5463 		return ("I_T Nexus Reset");
5464 	case SAS_CLEAR_ACA:
5465 		return ("Clear ACA");
5466 	case SAS_QUERY_TASK:
5467 		return ("Query Task");
5468 	case SAS_QUERY_TASK_SET:
5469 		return ("Query Task Set");
5470 	case SAS_QUERY_UNIT_ATTENTION:
5471 		return ("Query Unit Attention");
5472 	default:
5473 		return ("Unknown");
5474 	}
5475 }
5476 
5477 const char *
5478 pmcs_status_str(uint32_t status)
5479 {
5480 	switch (status) {
5481 	case PMCOUT_STATUS_OK:
5482 		return ("OK");
5483 	case PMCOUT_STATUS_ABORTED:
5484 		return ("ABORTED");
5485 	case PMCOUT_STATUS_OVERFLOW:
5486 		return ("OVERFLOW");
5487 	case PMCOUT_STATUS_UNDERFLOW:
5488 		return ("UNDERFLOW");
5489 	case PMCOUT_STATUS_FAILED:
5490 		return ("FAILED");
5491 	case PMCOUT_STATUS_ABORT_RESET:
5492 		return ("ABORT_RESET");
5493 	case PMCOUT_STATUS_IO_NOT_VALID:
5494 		return ("IO_NOT_VALID");
5495 	case PMCOUT_STATUS_NO_DEVICE:
5496 		return ("NO_DEVICE");
5497 	case PMCOUT_STATUS_ILLEGAL_PARAMETER:
5498 		return ("ILLEGAL_PARAMETER");
5499 	case PMCOUT_STATUS_LINK_FAILURE:
5500 		return ("LINK_FAILURE");
5501 	case PMCOUT_STATUS_PROG_ERROR:
5502 		return ("PROG_ERROR");
5503 	case PMCOUT_STATUS_EDC_IN_ERROR:
5504 		return ("EDC_IN_ERROR");
5505 	case PMCOUT_STATUS_EDC_OUT_ERROR:
5506 		return ("EDC_OUT_ERROR");
5507 	case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
5508 		return ("ERROR_HW_TIMEOUT");
5509 	case PMCOUT_STATUS_XFER_ERR_BREAK:
5510 		return ("XFER_ERR_BREAK");
5511 	case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
5512 		return ("XFER_ERR_PHY_NOT_READY");
5513 	case PMCOUT_STATUS_OPEN_CNX_PROTOCOL_NOT_SUPPORTED:
5514 		return ("OPEN_CNX_PROTOCOL_NOT_SUPPORTED");
5515 	case PMCOUT_STATUS_OPEN_CNX_ERROR_ZONE_VIOLATION:
5516 		return ("OPEN_CNX_ERROR_ZONE_VIOLATION");
5517 	case PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK:
5518 		return ("OPEN_CNX_ERROR_BREAK");
5519 	case PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
5520 		return ("OPEN_CNX_ERROR_IT_NEXUS_LOSS");
5521 	case PMCOUT_STATUS_OPENCNX_ERROR_BAD_DESTINATION:
5522 		return ("OPENCNX_ERROR_BAD_DESTINATION");
5523 	case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
5524 		return ("OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED");
5525 	case PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
5526 		return ("OPEN_CNX_ERROR_STP_RESOURCES_BUSY");
5527 	case PMCOUT_STATUS_OPEN_CNX_ERROR_WRONG_DESTINATION:
5528 		return ("OPEN_CNX_ERROR_WRONG_DESTINATION");
5529 	case PMCOUT_STATUS_OPEN_CNX_ERROR_UNKNOWN_ERROR:
5530 		return ("OPEN_CNX_ERROR_UNKNOWN_ERROR");
5531 	case PMCOUT_STATUS_IO_XFER_ERROR_NAK_RECEIVED:
5532 		return ("IO_XFER_ERROR_NAK_RECEIVED");
5533 	case PMCOUT_STATUS_XFER_ERROR_ACK_NAK_TIMEOUT:
5534 		return ("XFER_ERROR_ACK_NAK_TIMEOUT");
5535 	case PMCOUT_STATUS_XFER_ERROR_PEER_ABORTED:
5536 		return ("XFER_ERROR_PEER_ABORTED");
5537 	case PMCOUT_STATUS_XFER_ERROR_RX_FRAME:
5538 		return ("XFER_ERROR_RX_FRAME");
5539 	case PMCOUT_STATUS_IO_XFER_ERROR_DMA:
5540 		return ("IO_XFER_ERROR_DMA");
5541 	case PMCOUT_STATUS_XFER_ERROR_CREDIT_TIMEOUT:
5542 		return ("XFER_ERROR_CREDIT_TIMEOUT");
5543 	case PMCOUT_STATUS_XFER_ERROR_SATA_LINK_TIMEOUT:
5544 		return ("XFER_ERROR_SATA_LINK_TIMEOUT");
5545 	case PMCOUT_STATUS_XFER_ERROR_SATA:
5546 		return ("XFER_ERROR_SATA");
5547 	case PMCOUT_STATUS_XFER_ERROR_REJECTED_NCQ_MODE:
5548 		return ("XFER_ERROR_REJECTED_NCQ_MODE");
5549 	case PMCOUT_STATUS_XFER_ERROR_ABORTED_DUE_TO_SRST:
5550 		return ("XFER_ERROR_ABORTED_DUE_TO_SRST");
5551 	case PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE:
5552 		return ("XFER_ERROR_ABORTED_NCQ_MODE");
5553 	case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
5554 		return ("IO_XFER_OPEN_RETRY_TIMEOUT");
5555 	case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
5556 		return ("SMP_RESP_CONNECTION_ERROR");
5557 	case PMCOUT_STATUS_XFER_ERROR_UNEXPECTED_PHASE:
5558 		return ("XFER_ERROR_UNEXPECTED_PHASE");
5559 	case PMCOUT_STATUS_XFER_ERROR_RDY_OVERRUN:
5560 		return ("XFER_ERROR_RDY_OVERRUN");
5561 	case PMCOUT_STATUS_XFER_ERROR_RDY_NOT_EXPECTED:
5562 		return ("XFER_ERROR_RDY_NOT_EXPECTED");
5563 	case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
5564 		return ("XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT");
5565 	case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK:
5566 		return ("XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK");
5567 	case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK:
5568 		return ("XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK");
5569 	case PMCOUT_STATUS_XFER_ERROR_OFFSET_MISMATCH:
5570 		return ("XFER_ERROR_OFFSET_MISMATCH");
5571 	case PMCOUT_STATUS_XFER_ERROR_ZERO_DATA_LEN:
5572 		return ("XFER_ERROR_ZERO_DATA_LEN");
5573 	case PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED:
5574 		return ("XFER_CMD_FRAME_ISSUED");
5575 	case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
5576 		return ("ERROR_INTERNAL_SMP_RESOURCE");
5577 	case PMCOUT_STATUS_IO_PORT_IN_RESET:
5578 		return ("IO_PORT_IN_RESET");
5579 	case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL:
5580 		return ("DEVICE STATE NON-OPERATIONAL");
5581 	case PMCOUT_STATUS_IO_DS_IN_RECOVERY:
5582 		return ("DEVICE STATE IN RECOVERY");
5583 	case PMCOUT_STATUS_IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
5584 		return ("OPEN CNX ERR HW RESOURCE BUSY");
5585 	default:
5586 		return (NULL);
5587 	}
5588 }
5589 
5590 uint64_t
5591 pmcs_barray2wwn(uint8_t ba[8])
5592 {
5593 	uint64_t result = 0;
5594 	int i;
5595 
5596 	for (i = 0; i < 8; i++) {
5597 		result <<= 8;
5598 		result |= ba[i];
5599 	}
5600 	return (result);
5601 }
5602 
5603 void
5604 pmcs_wwn2barray(uint64_t wwn, uint8_t ba[8])
5605 {
5606 	int i;
5607 	for (i = 0; i < 8; i++) {
5608 		ba[7 - i] = wwn & 0xff;
5609 		wwn >>= 8;
5610 	}
5611 }
5612 
5613 void
5614 pmcs_report_fwversion(pmcs_hw_t *pwp)
5615 {
5616 	const char *fwsupport;
5617 	switch (PMCS_FW_TYPE(pwp)) {
5618 	case PMCS_FW_TYPE_RELEASED:
5619 		fwsupport = "Released";
5620 		break;
5621 	case PMCS_FW_TYPE_DEVELOPMENT:
5622 		fwsupport = "Development";
5623 		break;
5624 	case PMCS_FW_TYPE_ALPHA:
5625 		fwsupport = "Alpha";
5626 		break;
5627 	case PMCS_FW_TYPE_BETA:
5628 		fwsupport = "Beta";
5629 		break;
5630 	default:
5631 		fwsupport = "Special";
5632 		break;
5633 	}
5634 	pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5635 	    "Chip Revision: %c; F/W Revision %x.%x.%x %s (ILA rev %08x)",
5636 	    'A' + pwp->chiprev, PMCS_FW_MAJOR(pwp), PMCS_FW_MINOR(pwp),
5637 	    PMCS_FW_MICRO(pwp), fwsupport, pwp->ila_ver);
5638 }
5639 
5640 void
5641 pmcs_phy_name(pmcs_hw_t *pwp, pmcs_phy_t *pptr, char *obuf, size_t olen)
5642 {
5643 	if (pptr->parent) {
5644 		pmcs_phy_name(pwp, pptr->parent, obuf, olen);
5645 		(void) snprintf(obuf, olen, "%s.%02x", obuf, pptr->phynum);
5646 	} else {
5647 		(void) snprintf(obuf, olen, "pp%02x", pptr->phynum);
5648 	}
5649 }
5650 
5651 /*
5652  * Implementation for pmcs_find_phy_by_devid.
5653  * If the PHY is found, it is returned locked.
5654  */
5655 static pmcs_phy_t *
5656 pmcs_find_phy_by_devid_impl(pmcs_phy_t *phyp, uint32_t device_id)
5657 {
5658 	pmcs_phy_t *match, *cphyp, *nphyp;
5659 
5660 	ASSERT(!mutex_owned(&phyp->phy_lock));
5661 
5662 	while (phyp) {
5663 		pmcs_lock_phy(phyp);
5664 
5665 		if ((phyp->valid_device_id) && (phyp->device_id == device_id)) {
5666 			return (phyp);
5667 		}
5668 		if (phyp->children) {
5669 			cphyp = phyp->children;
5670 			pmcs_unlock_phy(phyp);
5671 			match = pmcs_find_phy_by_devid_impl(cphyp, device_id);
5672 			if (match) {
5673 				ASSERT(mutex_owned(&match->phy_lock));
5674 				return (match);
5675 			}
5676 			pmcs_lock_phy(phyp);
5677 		}
5678 
5679 		if (IS_ROOT_PHY(phyp)) {
5680 			pmcs_unlock_phy(phyp);
5681 			phyp = NULL;
5682 		} else {
5683 			nphyp = phyp->sibling;
5684 			pmcs_unlock_phy(phyp);
5685 			phyp = nphyp;
5686 		}
5687 	}
5688 
5689 	return (NULL);
5690 }
5691 
5692 /*
5693  * If the PHY is found, it is returned locked
5694  */
5695 pmcs_phy_t *
5696 pmcs_find_phy_by_devid(pmcs_hw_t *pwp, uint32_t device_id)
5697 {
5698 	pmcs_phy_t *phyp, *match = NULL;
5699 
5700 	phyp = pwp->root_phys;
5701 
5702 	while (phyp) {
5703 		match = pmcs_find_phy_by_devid_impl(phyp, device_id);
5704 		if (match) {
5705 			ASSERT(mutex_owned(&match->phy_lock));
5706 			return (match);
5707 		}
5708 		phyp = phyp->sibling;
5709 	}
5710 
5711 	return (NULL);
5712 }
5713 
5714 /*
5715  * This function is called as a sanity check to ensure that a newly registered
5716  * PHY doesn't have a device_id that exists with another registered PHY.
5717  */
5718 static boolean_t
5719 pmcs_validate_devid(pmcs_phy_t *parent, pmcs_phy_t *phyp, uint32_t device_id)
5720 {
5721 	pmcs_phy_t *pptr, *pchild;
5722 	boolean_t rval;
5723 
5724 	pptr = parent;
5725 
5726 	while (pptr) {
5727 		if (pptr->valid_device_id && (pptr != phyp) &&
5728 		    (pptr->device_id == device_id)) {
5729 			/*
5730 			 * This can still be OK if both of these PHYs actually
5731 			 * represent the same device (e.g. expander).  It could
5732 			 * be a case of a new "primary" PHY.  If the SAS address
5733 			 * is the same and they have the same parent, we'll
5734 			 * accept this if the PHY to be registered is the
5735 			 * primary.
5736 			 */
5737 			if ((phyp->parent == pptr->parent) &&
5738 			    (memcmp(phyp->sas_address,
5739 			    pptr->sas_address, 8) == 0) && (phyp->width > 1)) {
5740 				/*
5741 				 * Move children over to the new primary and
5742 				 * update both PHYs
5743 				 */
5744 				pmcs_lock_phy(pptr);
5745 				phyp->children = pptr->children;
5746 				pchild = phyp->children;
5747 				while (pchild) {
5748 					pchild->parent = phyp;
5749 					pchild = pchild->sibling;
5750 				}
5751 				phyp->subsidiary = 0;
5752 				phyp->ncphy = pptr->ncphy;
5753 				/*
5754 				 * device_id, valid_device_id, and configured
5755 				 * will be set by the caller
5756 				 */
5757 				pptr->children = NULL;
5758 				pptr->subsidiary = 1;
5759 				pptr->ncphy = 0;
5760 				pmcs_unlock_phy(pptr);
5761 				pmcs_prt(pptr->pwp, PMCS_PRT_DEBUG, pptr, NULL,
5762 				    "%s: Moving device_id %d from PHY %s to %s",
5763 				    __func__, device_id, pptr->path,
5764 				    phyp->path);
5765 				return (B_TRUE);
5766 			}
5767 			pmcs_prt(pptr->pwp, PMCS_PRT_DEBUG, pptr, NULL,
5768 			    "%s: phy %s already exists as %s with "
5769 			    "device id 0x%x", __func__, phyp->path,
5770 			    pptr->path, device_id);
5771 			return (B_FALSE);
5772 		}
5773 
5774 		if (pptr->children) {
5775 			rval = pmcs_validate_devid(pptr->children, phyp,
5776 			    device_id);
5777 			if (rval == B_FALSE) {
5778 				return (rval);
5779 			}
5780 		}
5781 
5782 		pptr = pptr->sibling;
5783 	}
5784 
5785 	/* This PHY and device_id are valid */
5786 	return (B_TRUE);
5787 }
5788 
5789 /*
5790  * If the PHY is found, it is returned locked
5791  */
5792 static pmcs_phy_t *
5793 pmcs_find_phy_by_wwn_impl(pmcs_phy_t *phyp, uint8_t *wwn)
5794 {
5795 	pmcs_phy_t *matched_phy, *cphyp, *nphyp;
5796 
5797 	ASSERT(!mutex_owned(&phyp->phy_lock));
5798 
5799 	while (phyp) {
5800 		pmcs_lock_phy(phyp);
5801 
5802 		if (phyp->valid_device_id) {
5803 			if (memcmp(phyp->sas_address, wwn, 8) == 0) {
5804 				return (phyp);
5805 			}
5806 		}
5807 
5808 		if (phyp->children) {
5809 			cphyp = phyp->children;
5810 			pmcs_unlock_phy(phyp);
5811 			matched_phy = pmcs_find_phy_by_wwn_impl(cphyp, wwn);
5812 			if (matched_phy) {
5813 				ASSERT(mutex_owned(&matched_phy->phy_lock));
5814 				return (matched_phy);
5815 			}
5816 			pmcs_lock_phy(phyp);
5817 		}
5818 
5819 		/*
5820 		 * Only iterate through non-root PHYs
5821 		 */
5822 		if (IS_ROOT_PHY(phyp)) {
5823 			pmcs_unlock_phy(phyp);
5824 			phyp = NULL;
5825 		} else {
5826 			nphyp = phyp->sibling;
5827 			pmcs_unlock_phy(phyp);
5828 			phyp = nphyp;
5829 		}
5830 	}
5831 
5832 	return (NULL);
5833 }
5834 
5835 pmcs_phy_t *
5836 pmcs_find_phy_by_wwn(pmcs_hw_t *pwp, uint64_t wwn)
5837 {
5838 	uint8_t ebstr[8];
5839 	pmcs_phy_t *pptr, *matched_phy;
5840 
5841 	pmcs_wwn2barray(wwn, ebstr);
5842 
5843 	pptr = pwp->root_phys;
5844 	while (pptr) {
5845 		matched_phy = pmcs_find_phy_by_wwn_impl(pptr, ebstr);
5846 		if (matched_phy) {
5847 			ASSERT(mutex_owned(&matched_phy->phy_lock));
5848 			return (matched_phy);
5849 		}
5850 
5851 		pptr = pptr->sibling;
5852 	}
5853 
5854 	return (NULL);
5855 }
5856 
5857 
5858 /*
5859  * pmcs_find_phy_by_sas_address
5860  *
5861  * Find a PHY that both matches "sas_addr" and is on "iport".
5862  * If a matching PHY is found, it is returned locked.
5863  */
5864 pmcs_phy_t *
5865 pmcs_find_phy_by_sas_address(pmcs_hw_t *pwp, pmcs_iport_t *iport,
5866     pmcs_phy_t *root, char *sas_addr)
5867 {
5868 	int ua_form = 1;
5869 	uint64_t wwn;
5870 	char addr[PMCS_MAX_UA_SIZE];
5871 	pmcs_phy_t *pptr, *pnext, *pchild;
5872 
5873 	if (root == NULL) {
5874 		pptr = pwp->root_phys;
5875 	} else {
5876 		pptr = root;
5877 	}
5878 
5879 	while (pptr) {
5880 		pmcs_lock_phy(pptr);
5881 		/*
5882 		 * If the PHY is dead or does not have a valid device ID,
5883 		 * skip it.
5884 		 */
5885 		if ((pptr->dead) || (!pptr->valid_device_id)) {
5886 			goto next_phy;
5887 		}
5888 
5889 		if (pptr->iport != iport) {
5890 			goto next_phy;
5891 		}
5892 
5893 		wwn = pmcs_barray2wwn(pptr->sas_address);
5894 		(void *) scsi_wwn_to_wwnstr(wwn, ua_form, addr);
5895 		if (strncmp(addr, sas_addr, strlen(addr)) == 0) {
5896 			return (pptr);
5897 		}
5898 
5899 		if (pptr->children) {
5900 			pchild = pptr->children;
5901 			pmcs_unlock_phy(pptr);
5902 			pnext = pmcs_find_phy_by_sas_address(pwp, iport, pchild,
5903 			    sas_addr);
5904 			if (pnext) {
5905 				return (pnext);
5906 			}
5907 			pmcs_lock_phy(pptr);
5908 		}
5909 
5910 next_phy:
5911 		pnext = pptr->sibling;
5912 		pmcs_unlock_phy(pptr);
5913 		pptr = pnext;
5914 	}
5915 
5916 	return (NULL);
5917 }
5918 
5919 void
5920 pmcs_fis_dump(pmcs_hw_t *pwp, fis_t fis)
5921 {
5922 	switch (fis[0] & 0xff) {
5923 	case FIS_REG_H2DEV:
5924 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5925 		    "FIS REGISTER HOST TO DEVICE: "
5926 		    "OP=0x%02x Feature=0x%04x Count=0x%04x Device=0x%02x "
5927 		    "LBA=%llu", BYTE2(fis[0]), BYTE3(fis[2]) << 8 |
5928 		    BYTE3(fis[0]), WORD0(fis[3]), BYTE3(fis[1]),
5929 		    (unsigned long long)
5930 		    (((uint64_t)fis[2] & 0x00ffffff) << 24 |
5931 		    ((uint64_t)fis[1] & 0x00ffffff)));
5932 		break;
5933 	case FIS_REG_D2H:
5934 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5935 		    "FIS REGISTER DEVICE TO HOST: Status=0x%02x "
5936 		    "Error=0x%02x Dev=0x%02x Count=0x%04x LBA=%llu",
5937 		    BYTE2(fis[0]), BYTE3(fis[0]), BYTE3(fis[1]), WORD0(fis[3]),
5938 		    (unsigned long long)(((uint64_t)fis[2] & 0x00ffffff) << 24 |
5939 		    ((uint64_t)fis[1] & 0x00ffffff)));
5940 		break;
5941 	default:
5942 		pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL,
5943 		    "FIS: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
5944 		    fis[0], fis[1], fis[2], fis[3], fis[4]);
5945 		break;
5946 	}
5947 }
5948 
5949 void
5950 pmcs_print_entry(pmcs_hw_t *pwp, int level, char *msg, void *arg)
5951 {
5952 	uint32_t *mb = arg;
5953 	size_t i;
5954 
5955 	pmcs_prt(pwp, level, NULL, NULL, msg);
5956 	for (i = 0; i < (PMCS_QENTRY_SIZE / sizeof (uint32_t)); i += 4) {
5957 		pmcs_prt(pwp, level, NULL, NULL,
5958 		    "Offset %2lu: 0x%08x 0x%08x 0x%08x 0x%08x",
5959 		    i * sizeof (uint32_t), LE_32(mb[i]),
5960 		    LE_32(mb[i+1]), LE_32(mb[i+2]), LE_32(mb[i+3]));
5961 	}
5962 }
5963 
5964 /*
5965  * If phyp == NULL we're being called from the worker thread, in which
5966  * case we need to check all the PHYs.  In this case, the softstate lock
5967  * will be held.
5968  * If phyp is non-NULL, just issue the spinup release for the specified PHY
5969  * (which will already be locked).
5970  */
5971 void
5972 pmcs_spinup_release(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
5973 {
5974 	uint32_t *msg;
5975 	struct pmcwork *pwrk;
5976 	pmcs_phy_t *tphyp;
5977 
5978 	if (phyp != NULL) {
5979 		ASSERT(mutex_owned(&phyp->phy_lock));
5980 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, NULL,
5981 		    "%s: Issuing spinup release only for PHY %s", __func__,
5982 		    phyp->path);
5983 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5984 		msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
5985 		if (msg == NULL || (pwrk =
5986 		    pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
5987 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
5988 			SCHEDULE_WORK(pwp, PMCS_WORK_SPINUP_RELEASE);
5989 			return;
5990 		}
5991 
5992 		phyp->spinup_hold = 0;
5993 		bzero(msg, PMCS_QENTRY_SIZE);
5994 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
5995 		    PMCIN_LOCAL_PHY_CONTROL));
5996 		msg[1] = LE_32(pwrk->htag);
5997 		msg[2] = LE_32((0x10 << 8) | phyp->phynum);
5998 
5999 		pwrk->dtype = phyp->dtype;
6000 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
6001 		mutex_exit(&pwrk->lock);
6002 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6003 		return;
6004 	}
6005 
6006 	ASSERT(mutex_owned(&pwp->lock));
6007 
6008 	tphyp = pwp->root_phys;
6009 	while (tphyp) {
6010 		pmcs_lock_phy(tphyp);
6011 		if (tphyp->spinup_hold == 0) {
6012 			pmcs_unlock_phy(tphyp);
6013 			tphyp = tphyp->sibling;
6014 			continue;
6015 		}
6016 
6017 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, NULL,
6018 		    "%s: Issuing spinup release for PHY %s", __func__,
6019 		    phyp->path);
6020 
6021 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6022 		msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6023 		if (msg == NULL || (pwrk =
6024 		    pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
6025 			pmcs_unlock_phy(tphyp);
6026 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6027 			SCHEDULE_WORK(pwp, PMCS_WORK_SPINUP_RELEASE);
6028 			break;
6029 		}
6030 
6031 		tphyp->spinup_hold = 0;
6032 		bzero(msg, PMCS_QENTRY_SIZE);
6033 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
6034 		    PMCIN_LOCAL_PHY_CONTROL));
6035 		msg[1] = LE_32(pwrk->htag);
6036 		msg[2] = LE_32((0x10 << 8) | tphyp->phynum);
6037 
6038 		pwrk->dtype = phyp->dtype;
6039 		pwrk->state = PMCS_WORK_STATE_ONCHIP;
6040 		mutex_exit(&pwrk->lock);
6041 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6042 		pmcs_unlock_phy(tphyp);
6043 
6044 		tphyp = tphyp->sibling;
6045 	}
6046 }
6047 
6048 /*
6049  * Abort commands on dead PHYs and deregister them as well as removing
6050  * the associated targets.
6051  */
6052 static int
6053 pmcs_kill_devices(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
6054 {
6055 	pmcs_phy_t *pnext, *pchild;
6056 	boolean_t remove_device;
6057 	int rval = 0;
6058 
6059 	while (phyp) {
6060 		pmcs_lock_phy(phyp);
6061 		pchild = phyp->children;
6062 		pnext = phyp->sibling;
6063 		pmcs_unlock_phy(phyp);
6064 
6065 		if (pchild) {
6066 			rval = pmcs_kill_devices(pwp, pchild);
6067 			if (rval) {
6068 				return (rval);
6069 			}
6070 		}
6071 
6072 		/*
6073 		 * pmcs_remove_device requires the softstate lock.
6074 		 */
6075 		mutex_enter(&pwp->lock);
6076 		pmcs_lock_phy(phyp);
6077 		if (phyp->dead && phyp->valid_device_id) {
6078 			remove_device = B_TRUE;
6079 		} else {
6080 			remove_device = B_FALSE;
6081 		}
6082 
6083 		if (remove_device) {
6084 			pmcs_remove_device(pwp, phyp);
6085 			mutex_exit(&pwp->lock);
6086 
6087 			rval = pmcs_kill_device(pwp, phyp);
6088 
6089 			if (rval) {
6090 				pmcs_unlock_phy(phyp);
6091 				return (rval);
6092 			}
6093 		} else {
6094 			mutex_exit(&pwp->lock);
6095 		}
6096 
6097 		pmcs_unlock_phy(phyp);
6098 		phyp = pnext;
6099 	}
6100 
6101 	return (rval);
6102 }
6103 
6104 /*
6105  * Called with PHY locked
6106  */
6107 int
6108 pmcs_kill_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
6109 {
6110 	int r, result;
6111 	uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
6112 	struct pmcwork *pwrk;
6113 
6114 	pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "kill %s device @ %s",
6115 	    pmcs_get_typename(pptr->dtype), pptr->path);
6116 
6117 	/*
6118 	 * There may be an outstanding ABORT_ALL running, which we wouldn't
6119 	 * know just by checking abort_pending.  We can, however, check
6120 	 * abort_all_start.  If it's non-zero, there is one, and we'll just
6121 	 * sit here and wait for it to complete.  If we don't, we'll remove
6122 	 * the device while there are still commands pending.
6123 	 */
6124 	if (pptr->abort_all_start) {
6125 		while (pptr->abort_all_start) {
6126 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
6127 			    "%s: Waiting for outstanding ABORT_ALL on PHY 0x%p",
6128 			    __func__, (void *)pptr);
6129 			cv_wait(&pptr->abort_all_cv, &pptr->phy_lock);
6130 		}
6131 	} else if (pptr->abort_pending) {
6132 		r = pmcs_abort(pwp, pptr, pptr->device_id, 1, 1);
6133 
6134 		if (r) {
6135 			pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
6136 			    "%s: ABORT_ALL returned non-zero status (%d) for "
6137 			    "PHY 0x%p", __func__, r, (void *)pptr);
6138 			return (r);
6139 		}
6140 		pptr->abort_pending = 0;
6141 	}
6142 
6143 	if (pptr->valid_device_id == 0) {
6144 		return (0);
6145 	}
6146 
6147 	if ((pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr)) == NULL) {
6148 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nowrk, __func__);
6149 		return (ENOMEM);
6150 	}
6151 	pwrk->arg = msg;
6152 	pwrk->dtype = pptr->dtype;
6153 	msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
6154 	    PMCIN_DEREGISTER_DEVICE_HANDLE));
6155 	msg[1] = LE_32(pwrk->htag);
6156 	msg[2] = LE_32(pptr->device_id);
6157 
6158 	mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6159 	ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6160 	if (ptr == NULL) {
6161 		mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6162 		mutex_exit(&pwrk->lock);
6163 		pmcs_prt(pwp, PMCS_PRT_ERR, pptr, NULL, pmcs_nomsg, __func__);
6164 		return (ENOMEM);
6165 	}
6166 
6167 	COPY_MESSAGE(ptr, msg, 3);
6168 	pwrk->state = PMCS_WORK_STATE_ONCHIP;
6169 	INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6170 
6171 	pmcs_unlock_phy(pptr);
6172 	WAIT_FOR(pwrk, 250, result);
6173 	pmcs_lock_phy(pptr);
6174 	pmcs_pwork(pwp, pwrk);
6175 
6176 	if (result) {
6177 		return (ETIMEDOUT);
6178 	}
6179 	status = LE_32(msg[2]);
6180 	if (status != PMCOUT_STATUS_OK) {
6181 		pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
6182 		    "%s: status 0x%x when trying to deregister device %s",
6183 		    __func__, status, pptr->path);
6184 	}
6185 
6186 	pptr->device_id = PMCS_INVALID_DEVICE_ID;
6187 	PHY_CHANGED(pwp, pptr);
6188 	RESTART_DISCOVERY(pwp);
6189 	pptr->valid_device_id = 0;
6190 	return (0);
6191 }
6192 
6193 /*
6194  * Acknowledge the SAS h/w events that need acknowledgement.
6195  * This is only needed for first level PHYs.
6196  */
6197 void
6198 pmcs_ack_events(pmcs_hw_t *pwp)
6199 {
6200 	uint32_t msg[PMCS_MSG_SIZE], *ptr;
6201 	struct pmcwork *pwrk;
6202 	pmcs_phy_t *pptr;
6203 
6204 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
6205 		pmcs_lock_phy(pptr);
6206 		if (pptr->hw_event_ack == 0) {
6207 			pmcs_unlock_phy(pptr);
6208 			continue;
6209 		}
6210 		mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6211 		ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6212 
6213 		if ((ptr == NULL) || (pwrk =
6214 		    pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
6215 			mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
6216 			pmcs_unlock_phy(pptr);
6217 			SCHEDULE_WORK(pwp, PMCS_WORK_SAS_HW_ACK);
6218 			break;
6219 		}
6220 
6221 		msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
6222 		    PMCIN_SAW_HW_EVENT_ACK));
6223 		msg[1] = LE_32(pwrk->htag);
6224 		msg[2] = LE_32(pptr->hw_event_ack);
6225 
6226 		mutex_exit(&pwrk->lock);
6227 		pwrk->dtype = pptr->dtype;
6228 		pptr->hw_event_ack = 0;
6229 		COPY_MESSAGE(ptr, msg, 3);
6230 		INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
6231 		pmcs_unlock_phy(pptr);
6232 	}
6233 }
6234 
6235 /*
6236  * Load DMA
6237  */
6238 int
6239 pmcs_dma_load(pmcs_hw_t *pwp, pmcs_cmd_t *sp, uint32_t *msg)
6240 {
6241 	ddi_dma_cookie_t *sg;
6242 	pmcs_dmachunk_t *tc;
6243 	pmcs_dmasgl_t *sgl, *prior;
6244 	int seg, tsc;
6245 	uint64_t sgl_addr;
6246 
6247 	/*
6248 	 * If we have no data segments, we're done.
6249 	 */
6250 	if (CMD2PKT(sp)->pkt_numcookies == 0) {
6251 		return (0);
6252 	}
6253 
6254 	/*
6255 	 * Get the S/G list pointer.
6256 	 */
6257 	sg = CMD2PKT(sp)->pkt_cookies;
6258 
6259 	/*
6260 	 * If we only have one dma segment, we can directly address that
6261 	 * data within the Inbound message itself.
6262 	 */
6263 	if (CMD2PKT(sp)->pkt_numcookies == 1) {
6264 		msg[12] = LE_32(DWORD0(sg->dmac_laddress));
6265 		msg[13] = LE_32(DWORD1(sg->dmac_laddress));
6266 		msg[14] = LE_32(sg->dmac_size);
6267 		msg[15] = 0;
6268 		return (0);
6269 	}
6270 
6271 	/*
6272 	 * Otherwise, we'll need one or more external S/G list chunks.
6273 	 * Get the first one and its dma address into the Inbound message.
6274 	 */
6275 	mutex_enter(&pwp->dma_lock);
6276 	tc = pwp->dma_freelist;
6277 	if (tc == NULL) {
6278 		SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
6279 		mutex_exit(&pwp->dma_lock);
6280 		pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
6281 		    "%s: out of SG lists", __func__);
6282 		return (-1);
6283 	}
6284 	pwp->dma_freelist = tc->nxt;
6285 	mutex_exit(&pwp->dma_lock);
6286 
6287 	tc->nxt = NULL;
6288 	sp->cmd_clist = tc;
6289 	sgl = tc->chunks;
6290 	(void) memset(tc->chunks, 0, PMCS_SGL_CHUNKSZ);
6291 	sgl_addr = tc->addr;
6292 	msg[12] = LE_32(DWORD0(sgl_addr));
6293 	msg[13] = LE_32(DWORD1(sgl_addr));
6294 	msg[14] = 0;
6295 	msg[15] = LE_32(PMCS_DMASGL_EXTENSION);
6296 
6297 	prior = sgl;
6298 	tsc = 0;
6299 
6300 	for (seg = 0; seg < CMD2PKT(sp)->pkt_numcookies; seg++) {
6301 		/*
6302 		 * If the current segment count for this chunk is one less than
6303 		 * the number s/g lists per chunk and we have more than one seg
6304 		 * to go, we need another chunk. Get it, and make sure that the
6305 		 * tail end of the the previous chunk points the new chunk
6306 		 * (if remembering an offset can be called 'pointing to').
6307 		 *
6308 		 * Note that we can store the offset into our command area that
6309 		 * represents the new chunk in the length field of the part
6310 		 * that points the PMC chip at the next chunk- the PMC chip
6311 		 * ignores this field when the EXTENSION bit is set.
6312 		 *
6313 		 * This is required for dma unloads later.
6314 		 */
6315 		if (tsc == (PMCS_SGL_NCHUNKS - 1) &&
6316 		    seg < (CMD2PKT(sp)->pkt_numcookies - 1)) {
6317 			mutex_enter(&pwp->dma_lock);
6318 			tc = pwp->dma_freelist;
6319 			if (tc == NULL) {
6320 				SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
6321 				mutex_exit(&pwp->dma_lock);
6322 				pmcs_dma_unload(pwp, sp);
6323 				pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
6324 				    "%s: out of SG lists", __func__);
6325 				return (-1);
6326 			}
6327 			pwp->dma_freelist = tc->nxt;
6328 			tc->nxt = sp->cmd_clist;
6329 			mutex_exit(&pwp->dma_lock);
6330 
6331 			sp->cmd_clist = tc;
6332 			(void) memset(tc->chunks, 0, PMCS_SGL_CHUNKSZ);
6333 			sgl = tc->chunks;
6334 			sgl_addr = tc->addr;
6335 			prior[PMCS_SGL_NCHUNKS-1].sglal =
6336 			    LE_32(DWORD0(sgl_addr));
6337 			prior[PMCS_SGL_NCHUNKS-1].sglah =
6338 			    LE_32(DWORD1(sgl_addr));
6339 			prior[PMCS_SGL_NCHUNKS-1].sglen = 0;
6340 			prior[PMCS_SGL_NCHUNKS-1].flags =
6341 			    LE_32(PMCS_DMASGL_EXTENSION);
6342 			prior = sgl;
6343 			tsc = 0;
6344 		}
6345 		sgl[tsc].sglal = LE_32(DWORD0(sg->dmac_laddress));
6346 		sgl[tsc].sglah = LE_32(DWORD1(sg->dmac_laddress));
6347 		sgl[tsc].sglen = LE_32(sg->dmac_size);
6348 		sgl[tsc++].flags = 0;
6349 		sg++;
6350 	}
6351 	return (0);
6352 }
6353 
6354 /*
6355  * Unload DMA
6356  */
6357 void
6358 pmcs_dma_unload(pmcs_hw_t *pwp, pmcs_cmd_t *sp)
6359 {
6360 	pmcs_dmachunk_t *cp;
6361 
6362 	mutex_enter(&pwp->dma_lock);
6363 	while ((cp = sp->cmd_clist) != NULL) {
6364 		sp->cmd_clist = cp->nxt;
6365 		cp->nxt = pwp->dma_freelist;
6366 		pwp->dma_freelist = cp;
6367 	}
6368 	mutex_exit(&pwp->dma_lock);
6369 }
6370 
6371 /*
6372  * Take a chunk of consistent memory that has just been allocated and inserted
6373  * into the cip indices and prepare it for DMA chunk usage and add it to the
6374  * freelist.
6375  *
6376  * Called with dma_lock locked (except during attach when it's unnecessary)
6377  */
6378 void
6379 pmcs_idma_chunks(pmcs_hw_t *pwp, pmcs_dmachunk_t *dcp,
6380     pmcs_chunk_t *pchunk, unsigned long lim)
6381 {
6382 	unsigned long off, n;
6383 	pmcs_dmachunk_t *np = dcp;
6384 	pmcs_chunk_t *tmp_chunk;
6385 
6386 	if (pwp->dma_chunklist == NULL) {
6387 		pwp->dma_chunklist = pchunk;
6388 	} else {
6389 		tmp_chunk = pwp->dma_chunklist;
6390 		while (tmp_chunk->next) {
6391 			tmp_chunk = tmp_chunk->next;
6392 		}
6393 		tmp_chunk->next = pchunk;
6394 	}
6395 
6396 	/*
6397 	 * Install offsets into chunk lists.
6398 	 */
6399 	for (n = 0, off = 0; off < lim; off += PMCS_SGL_CHUNKSZ, n++) {
6400 		np->chunks = (void *)&pchunk->addrp[off];
6401 		np->addr = pchunk->dma_addr + off;
6402 		np->acc_handle = pchunk->acc_handle;
6403 		np->dma_handle = pchunk->dma_handle;
6404 		if ((off + PMCS_SGL_CHUNKSZ) < lim) {
6405 			np = np->nxt;
6406 		}
6407 	}
6408 	np->nxt = pwp->dma_freelist;
6409 	pwp->dma_freelist = dcp;
6410 	pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
6411 	    "added %lu DMA chunks ", n);
6412 }
6413 
6414 /*
6415  * Change the value of the interrupt coalescing timer.  This is done currently
6416  * only for I/O completions.  If we're using the "auto clear" feature, it can
6417  * be turned back on when interrupt coalescing is turned off and must be
6418  * turned off when the coalescing timer is on.
6419  * NOTE: PMCS_MSIX_GENERAL and PMCS_OQ_IODONE are the same value.  As long
6420  * as that's true, we don't need to distinguish between them.
6421  */
6422 
6423 void
6424 pmcs_set_intr_coal_timer(pmcs_hw_t *pwp, pmcs_coal_timer_adj_t adj)
6425 {
6426 	if (adj == DECREASE_TIMER) {
6427 		/* If the timer is already off, nothing to do. */
6428 		if (pwp->io_intr_coal.timer_on == B_FALSE) {
6429 			return;
6430 		}
6431 
6432 		pwp->io_intr_coal.intr_coal_timer -= PMCS_COAL_TIMER_GRAN;
6433 
6434 		if (pwp->io_intr_coal.intr_coal_timer == 0) {
6435 			/* Disable the timer */
6436 			pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL, 0);
6437 
6438 			if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) {
6439 				pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR,
6440 				    pwp->odb_auto_clear);
6441 			}
6442 
6443 			pwp->io_intr_coal.timer_on = B_FALSE;
6444 			pwp->io_intr_coal.max_io_completions = B_FALSE;
6445 			pwp->io_intr_coal.num_intrs = 0;
6446 			pwp->io_intr_coal.int_cleared = B_FALSE;
6447 			pwp->io_intr_coal.num_io_completions = 0;
6448 
6449 			DTRACE_PROBE1(pmcs__intr__coalesce__timer__off,
6450 			    pmcs_io_intr_coal_t *, &pwp->io_intr_coal);
6451 		} else {
6452 			pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_TIMER,
6453 			    pwp->io_intr_coal.intr_coal_timer);
6454 		}
6455 	} else {
6456 		/*
6457 		 * If the timer isn't on yet, do the setup for it now.
6458 		 */
6459 		if (pwp->io_intr_coal.timer_on == B_FALSE) {
6460 			/* If auto clear is being used, turn it off. */
6461 			if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) {
6462 				pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR,
6463 				    (pwp->odb_auto_clear &
6464 				    ~(1 << PMCS_MSIX_IODONE)));
6465 			}
6466 
6467 			pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL,
6468 			    (1 << PMCS_MSIX_IODONE));
6469 			pwp->io_intr_coal.timer_on = B_TRUE;
6470 			pwp->io_intr_coal.intr_coal_timer =
6471 			    PMCS_COAL_TIMER_GRAN;
6472 
6473 			DTRACE_PROBE1(pmcs__intr__coalesce__timer__on,
6474 			    pmcs_io_intr_coal_t *, &pwp->io_intr_coal);
6475 		} else {
6476 			pwp->io_intr_coal.intr_coal_timer +=
6477 			    PMCS_COAL_TIMER_GRAN;
6478 		}
6479 
6480 		if (pwp->io_intr_coal.intr_coal_timer > PMCS_MAX_COAL_TIMER) {
6481 			pwp->io_intr_coal.intr_coal_timer = PMCS_MAX_COAL_TIMER;
6482 		}
6483 
6484 		pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_TIMER,
6485 		    pwp->io_intr_coal.intr_coal_timer);
6486 	}
6487 
6488 	/*
6489 	 * Adjust the interrupt threshold based on the current timer value
6490 	 */
6491 	pwp->io_intr_coal.intr_threshold =
6492 	    PMCS_INTR_THRESHOLD(PMCS_QUANTUM_TIME_USECS * 1000 /
6493 	    (pwp->io_intr_coal.intr_latency +
6494 	    (pwp->io_intr_coal.intr_coal_timer * 1000)));
6495 }
6496 
6497 /*
6498  * Register Access functions
6499  */
6500 uint32_t
6501 pmcs_rd_iqci(pmcs_hw_t *pwp, uint32_t qnum)
6502 {
6503 	uint32_t iqci;
6504 
6505 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORKERNEL) !=
6506 	    DDI_SUCCESS) {
6507 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6508 		    "%s: ddi_dma_sync failed?", __func__);
6509 	}
6510 
6511 	iqci = LE_32(
6512 	    ((uint32_t *)((void *)pwp->cip))[IQ_OFFSET(qnum) >> 2]);
6513 
6514 	return (iqci);
6515 }
6516 
6517 uint32_t
6518 pmcs_rd_oqpi(pmcs_hw_t *pwp, uint32_t qnum)
6519 {
6520 	uint32_t oqpi;
6521 
6522 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORKERNEL) !=
6523 	    DDI_SUCCESS) {
6524 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6525 		    "%s: ddi_dma_sync failed?", __func__);
6526 	}
6527 
6528 	oqpi = LE_32(
6529 	    ((uint32_t *)((void *)pwp->cip))[OQ_OFFSET(qnum) >> 2]);
6530 
6531 	return (oqpi);
6532 }
6533 
6534 uint32_t
6535 pmcs_rd_gsm_reg(pmcs_hw_t *pwp, uint8_t hi, uint32_t off)
6536 {
6537 	uint32_t rv, newaxil, oldaxil, oldaxih;
6538 
6539 	newaxil = off & ~GSM_BASE_MASK;
6540 	off &= GSM_BASE_MASK;
6541 	mutex_enter(&pwp->axil_lock);
6542 	oldaxil = ddi_get32(pwp->top_acc_handle,
6543 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
6544 	ddi_put32(pwp->top_acc_handle,
6545 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
6546 	drv_usecwait(10);
6547 	if (ddi_get32(pwp->top_acc_handle,
6548 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
6549 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6550 		    "AXIL register update failed");
6551 	}
6552 	if (hi) {
6553 		oldaxih = ddi_get32(pwp->top_acc_handle,
6554 		    &pwp->top_regs[PMCS_AXI_TRANS_UPPER >> 2]);
6555 		ddi_put32(pwp->top_acc_handle,
6556 		    &pwp->top_regs[PMCS_AXI_TRANS_UPPER >> 2], hi);
6557 		drv_usecwait(10);
6558 		if (ddi_get32(pwp->top_acc_handle,
6559 		    &pwp->top_regs[PMCS_AXI_TRANS_UPPER >> 2]) != hi) {
6560 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6561 			    "AXIH register update failed");
6562 		}
6563 	}
6564 	rv = ddi_get32(pwp->gsm_acc_handle, &pwp->gsm_regs[off >> 2]);
6565 	if (hi) {
6566 		ddi_put32(pwp->top_acc_handle,
6567 		    &pwp->top_regs[PMCS_AXI_TRANS_UPPER >> 2], oldaxih);
6568 		drv_usecwait(10);
6569 		if (ddi_get32(pwp->top_acc_handle,
6570 		    &pwp->top_regs[PMCS_AXI_TRANS_UPPER >> 2]) != oldaxih) {
6571 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6572 			    "AXIH register restore failed");
6573 		}
6574 	}
6575 	ddi_put32(pwp->top_acc_handle,
6576 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
6577 	drv_usecwait(10);
6578 	if (ddi_get32(pwp->top_acc_handle,
6579 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
6580 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6581 		    "AXIL register restore failed");
6582 	}
6583 	mutex_exit(&pwp->axil_lock);
6584 	return (rv);
6585 }
6586 
6587 void
6588 pmcs_wr_gsm_reg(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6589 {
6590 	uint32_t newaxil, oldaxil;
6591 
6592 	newaxil = off & ~GSM_BASE_MASK;
6593 	off &= GSM_BASE_MASK;
6594 	mutex_enter(&pwp->axil_lock);
6595 	oldaxil = ddi_get32(pwp->top_acc_handle,
6596 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
6597 	ddi_put32(pwp->top_acc_handle,
6598 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
6599 	drv_usecwait(10);
6600 	if (ddi_get32(pwp->top_acc_handle,
6601 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
6602 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6603 		    "AXIL register update failed");
6604 	}
6605 	ddi_put32(pwp->gsm_acc_handle, &pwp->gsm_regs[off >> 2], val);
6606 	ddi_put32(pwp->top_acc_handle,
6607 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
6608 	drv_usecwait(10);
6609 	if (ddi_get32(pwp->top_acc_handle,
6610 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
6611 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6612 		    "AXIL register restore failed");
6613 	}
6614 	mutex_exit(&pwp->axil_lock);
6615 }
6616 
6617 uint32_t
6618 pmcs_rd_topunit(pmcs_hw_t *pwp, uint32_t off)
6619 {
6620 	switch (off) {
6621 	case PMCS_SPC_RESET:
6622 	case PMCS_SPC_BOOT_STRAP:
6623 	case PMCS_SPC_DEVICE_ID:
6624 	case PMCS_DEVICE_REVISION:
6625 		off = pmcs_rd_gsm_reg(pwp, 0, off);
6626 		break;
6627 	default:
6628 		off = ddi_get32(pwp->top_acc_handle,
6629 		    &pwp->top_regs[off >> 2]);
6630 		break;
6631 	}
6632 	return (off);
6633 }
6634 
6635 void
6636 pmcs_wr_topunit(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6637 {
6638 	switch (off) {
6639 	case PMCS_SPC_RESET:
6640 	case PMCS_DEVICE_REVISION:
6641 		pmcs_wr_gsm_reg(pwp, off, val);
6642 		break;
6643 	default:
6644 		ddi_put32(pwp->top_acc_handle, &pwp->top_regs[off >> 2], val);
6645 		break;
6646 	}
6647 }
6648 
6649 uint32_t
6650 pmcs_rd_msgunit(pmcs_hw_t *pwp, uint32_t off)
6651 {
6652 	return (ddi_get32(pwp->msg_acc_handle, &pwp->msg_regs[off >> 2]));
6653 }
6654 
6655 uint32_t
6656 pmcs_rd_mpi_tbl(pmcs_hw_t *pwp, uint32_t off)
6657 {
6658 	return (ddi_get32(pwp->mpi_acc_handle,
6659 	    &pwp->mpi_regs[(pwp->mpi_offset + off) >> 2]));
6660 }
6661 
6662 uint32_t
6663 pmcs_rd_gst_tbl(pmcs_hw_t *pwp, uint32_t off)
6664 {
6665 	return (ddi_get32(pwp->mpi_acc_handle,
6666 	    &pwp->mpi_regs[(pwp->mpi_gst_offset + off) >> 2]));
6667 }
6668 
6669 uint32_t
6670 pmcs_rd_iqc_tbl(pmcs_hw_t *pwp, uint32_t off)
6671 {
6672 	return (ddi_get32(pwp->mpi_acc_handle,
6673 	    &pwp->mpi_regs[(pwp->mpi_iqc_offset + off) >> 2]));
6674 }
6675 
6676 uint32_t
6677 pmcs_rd_oqc_tbl(pmcs_hw_t *pwp, uint32_t off)
6678 {
6679 	return (ddi_get32(pwp->mpi_acc_handle,
6680 	    &pwp->mpi_regs[(pwp->mpi_oqc_offset + off) >> 2]));
6681 }
6682 
6683 uint32_t
6684 pmcs_rd_iqpi(pmcs_hw_t *pwp, uint32_t qnum)
6685 {
6686 	return (ddi_get32(pwp->mpi_acc_handle,
6687 	    &pwp->mpi_regs[pwp->iqpi_offset[qnum] >> 2]));
6688 }
6689 
6690 uint32_t
6691 pmcs_rd_oqci(pmcs_hw_t *pwp, uint32_t qnum)
6692 {
6693 	return (ddi_get32(pwp->mpi_acc_handle,
6694 	    &pwp->mpi_regs[pwp->oqci_offset[qnum] >> 2]));
6695 }
6696 
6697 void
6698 pmcs_wr_msgunit(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6699 {
6700 	ddi_put32(pwp->msg_acc_handle, &pwp->msg_regs[off >> 2], val);
6701 }
6702 
6703 void
6704 pmcs_wr_mpi_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6705 {
6706 	ddi_put32(pwp->mpi_acc_handle,
6707 	    &pwp->mpi_regs[(pwp->mpi_offset + off) >> 2], (val));
6708 }
6709 
6710 void
6711 pmcs_wr_gst_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6712 {
6713 	ddi_put32(pwp->mpi_acc_handle,
6714 	    &pwp->mpi_regs[(pwp->mpi_gst_offset + off) >> 2], val);
6715 }
6716 
6717 void
6718 pmcs_wr_iqc_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6719 {
6720 	ddi_put32(pwp->mpi_acc_handle,
6721 	    &pwp->mpi_regs[(pwp->mpi_iqc_offset + off) >> 2], val);
6722 }
6723 
6724 void
6725 pmcs_wr_oqc_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
6726 {
6727 	ddi_put32(pwp->mpi_acc_handle,
6728 	    &pwp->mpi_regs[(pwp->mpi_oqc_offset + off) >> 2], val);
6729 }
6730 
6731 void
6732 pmcs_wr_iqci(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6733 {
6734 	((uint32_t *)((void *)pwp->cip))[IQ_OFFSET(qnum) >> 2] = val;
6735 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORDEV) !=
6736 	    DDI_SUCCESS) {
6737 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6738 		    "%s: ddi_dma_sync failed?", __func__);
6739 	}
6740 }
6741 
6742 void
6743 pmcs_wr_iqpi(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6744 {
6745 	ddi_put32(pwp->mpi_acc_handle,
6746 	    &pwp->mpi_regs[pwp->iqpi_offset[qnum] >> 2], val);
6747 }
6748 
6749 void
6750 pmcs_wr_oqci(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6751 {
6752 	ddi_put32(pwp->mpi_acc_handle,
6753 	    &pwp->mpi_regs[pwp->oqci_offset[qnum] >> 2], val);
6754 }
6755 
6756 void
6757 pmcs_wr_oqpi(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
6758 {
6759 	((uint32_t *)((void *)pwp->cip))[OQ_OFFSET(qnum) >> 2] = val;
6760 	if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORDEV) !=
6761 	    DDI_SUCCESS) {
6762 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6763 		    "%s: ddi_dma_sync failed?", __func__);
6764 	}
6765 }
6766 
6767 /*
6768  * Check the status value of an outbound IOMB and report anything bad
6769  */
6770 
6771 void
6772 pmcs_check_iomb_status(pmcs_hw_t *pwp, uint32_t *iomb)
6773 {
6774 	uint16_t 	opcode;
6775 	int		offset;
6776 
6777 	if (iomb == NULL) {
6778 		return;
6779 	}
6780 
6781 	opcode = LE_32(iomb[0]) & 0xfff;
6782 
6783 	switch (opcode) {
6784 		/*
6785 		 * The following have no status field, so ignore them
6786 		 */
6787 	case PMCOUT_ECHO:
6788 	case PMCOUT_SAS_HW_EVENT:
6789 	case PMCOUT_GET_DEVICE_HANDLE:
6790 	case PMCOUT_SATA_EVENT:
6791 	case PMCOUT_SSP_EVENT:
6792 	case PMCOUT_DEVICE_HANDLE_ARRIVED:
6793 	case PMCOUT_SMP_REQUEST_RECEIVED:
6794 	case PMCOUT_GPIO:
6795 	case PMCOUT_GPIO_EVENT:
6796 	case PMCOUT_GET_TIME_STAMP:
6797 	case PMCOUT_SKIP_ENTRIES:
6798 	case PMCOUT_GET_NVMD_DATA:	/* Actually lower 16 bits of word 3 */
6799 	case PMCOUT_SET_NVMD_DATA:	/* but ignore - we don't use these */
6800 	case PMCOUT_DEVICE_HANDLE_REMOVED:
6801 	case PMCOUT_SSP_REQUEST_RECEIVED:
6802 		return;
6803 
6804 	case PMCOUT_GENERAL_EVENT:
6805 		offset = 1;
6806 		break;
6807 
6808 	case PMCOUT_SSP_COMPLETION:
6809 	case PMCOUT_SMP_COMPLETION:
6810 	case PMCOUT_DEVICE_REGISTRATION:
6811 	case PMCOUT_DEREGISTER_DEVICE_HANDLE:
6812 	case PMCOUT_SATA_COMPLETION:
6813 	case PMCOUT_DEVICE_INFO:
6814 	case PMCOUT_FW_FLASH_UPDATE:
6815 	case PMCOUT_SSP_ABORT:
6816 	case PMCOUT_SATA_ABORT:
6817 	case PMCOUT_SAS_DIAG_MODE_START_END:
6818 	case PMCOUT_SAS_HW_EVENT_ACK_ACK:
6819 	case PMCOUT_SMP_ABORT:
6820 	case PMCOUT_SET_DEVICE_STATE:
6821 	case PMCOUT_GET_DEVICE_STATE:
6822 	case PMCOUT_SET_DEVICE_INFO:
6823 		offset = 2;
6824 		break;
6825 
6826 	case PMCOUT_LOCAL_PHY_CONTROL:
6827 	case PMCOUT_SAS_DIAG_EXECUTE:
6828 	case PMCOUT_PORT_CONTROL:
6829 		offset = 3;
6830 		break;
6831 
6832 	case PMCOUT_GET_INFO:
6833 	case PMCOUT_GET_VPD:
6834 	case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
6835 	case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
6836 	case PMCOUT_SET_VPD:
6837 	case PMCOUT_TWI:
6838 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
6839 		    "Got response for deprecated opcode", iomb);
6840 		return;
6841 
6842 	default:
6843 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
6844 		    "Got response for unknown opcode", iomb);
6845 		return;
6846 	}
6847 
6848 	if (LE_32(iomb[offset]) != PMCOUT_STATUS_OK) {
6849 		pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
6850 		    "bad status on TAG_TYPE_NONE command", iomb);
6851 	}
6852 }
6853 
6854 /*
6855  * Called with statlock held
6856  */
6857 void
6858 pmcs_clear_xp(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
6859 {
6860 	_NOTE(ARGUNUSED(pwp));
6861 
6862 	ASSERT(mutex_owned(&xp->statlock));
6863 
6864 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp, "%s: Device 0x%p is gone.",
6865 	    __func__, (void *)xp);
6866 
6867 	/*
6868 	 * Clear the dip now.  This keeps pmcs_remove_device from attempting
6869 	 * to call us on the same device while we're still flushing queues.
6870 	 * The only side effect is we can no longer update SM-HBA properties,
6871 	 * but this device is going away anyway, so no matter.
6872 	 */
6873 	xp->dip = NULL;
6874 	xp->smpd = NULL;
6875 	xp->special_running = 0;
6876 	xp->recovering = 0;
6877 	xp->recover_wait = 0;
6878 	xp->draining = 0;
6879 	xp->new = 0;
6880 	xp->assigned = 0;
6881 	xp->dev_state = 0;
6882 	xp->tagmap = 0;
6883 	xp->dev_gone = 1;
6884 	xp->event_recovery = 0;
6885 	xp->dtype = NOTHING;
6886 	xp->wq_recovery_tail = NULL;
6887 	/* Don't clear xp->phy */
6888 	/* Don't clear xp->actv_cnt */
6889 	/* Don't clear xp->actv_pkts */
6890 
6891 	/*
6892 	 * Flush all target queues
6893 	 */
6894 	pmcs_flush_target_queues(pwp, xp, PMCS_TGT_ALL_QUEUES);
6895 }
6896 
6897 static int
6898 pmcs_smp_function_result(pmcs_hw_t *pwp, smp_response_frame_t *srf)
6899 {
6900 	int result = srf->srf_result;
6901 
6902 	switch (result) {
6903 	case SMP_RES_UNKNOWN_FUNCTION:
6904 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6905 		    "%s: SMP DISCOVER Response "
6906 		    "Function Result: Unknown SMP Function(0x%x)",
6907 		    __func__, result);
6908 		break;
6909 	case SMP_RES_FUNCTION_FAILED:
6910 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6911 		    "%s: SMP DISCOVER Response "
6912 		    "Function Result: SMP Function Failed(0x%x)",
6913 		    __func__, result);
6914 		break;
6915 	case SMP_RES_INVALID_REQUEST_FRAME_LENGTH:
6916 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6917 		    "%s: SMP DISCOVER Response "
6918 		    "Function Result: Invalid Request Frame Length(0x%x)",
6919 		    __func__, result);
6920 		break;
6921 	case SMP_RES_INCOMPLETE_DESCRIPTOR_LIST:
6922 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6923 		    "%s: SMP DISCOVER Response "
6924 		    "Function Result: Incomplete Descriptor List(0x%x)",
6925 		    __func__, result);
6926 		break;
6927 	case SMP_RES_PHY_DOES_NOT_EXIST:
6928 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6929 		    "%s: SMP DISCOVER Response "
6930 		    "Function Result: PHY does not exist(0x%x)",
6931 		    __func__, result);
6932 		break;
6933 	case SMP_RES_PHY_VACANT:
6934 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6935 		    "%s: SMP DISCOVER Response "
6936 		    "Function Result: PHY Vacant(0x%x)",
6937 		    __func__, result);
6938 		break;
6939 	default:
6940 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6941 		    "%s: SMP DISCOVER Response "
6942 		    "Function Result: (0x%x)",
6943 		    __func__, result);
6944 		break;
6945 	}
6946 
6947 	return (result);
6948 }
6949 
6950 /*
6951  * Do all the repetitive stuff necessary to setup for DMA
6952  *
6953  * pwp: Used for dip
6954  * dma_attr: ddi_dma_attr_t to use for the mapping
6955  * acch: ddi_acc_handle_t to use for the mapping
6956  * dmah: ddi_dma_handle_t to use
6957  * length: Amount of memory for mapping
6958  * kvap: Pointer filled in with kernel virtual address on successful return
6959  * dma_addr: Pointer filled in with DMA address on successful return
6960  */
6961 boolean_t
6962 pmcs_dma_setup(pmcs_hw_t *pwp, ddi_dma_attr_t *dma_attr, ddi_acc_handle_t *acch,
6963     ddi_dma_handle_t *dmah, size_t length, caddr_t *kvap, uint64_t *dma_addr)
6964 {
6965 	dev_info_t		*dip = pwp->dip;
6966 	ddi_dma_cookie_t	cookie;
6967 	size_t			real_length;
6968 	uint_t			ddma_flag = DDI_DMA_CONSISTENT;
6969 	uint_t			ddabh_flag = DDI_DMA_CONSISTENT | DDI_DMA_RDWR;
6970 	uint_t			cookie_cnt;
6971 	ddi_device_acc_attr_t	mattr = {
6972 		DDI_DEVICE_ATTR_V0,
6973 		DDI_NEVERSWAP_ACC,
6974 		DDI_STRICTORDER_ACC,
6975 		DDI_DEFAULT_ACC
6976 	};
6977 
6978 	*acch = NULL;
6979 	*dmah = NULL;
6980 
6981 	if (ddi_dma_alloc_handle(dip, dma_attr, DDI_DMA_SLEEP, NULL, dmah) !=
6982 	    DDI_SUCCESS) {
6983 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6984 		    "Failed to allocate DMA handle");
6985 		return (B_FALSE);
6986 	}
6987 
6988 	if (ddi_dma_mem_alloc(*dmah, length, &mattr, ddma_flag, DDI_DMA_SLEEP,
6989 	    NULL, kvap, &real_length, acch) != DDI_SUCCESS) {
6990 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6991 		    "Failed to allocate DMA mem");
6992 		ddi_dma_free_handle(dmah);
6993 		*dmah = NULL;
6994 		return (B_FALSE);
6995 	}
6996 
6997 	if (ddi_dma_addr_bind_handle(*dmah, NULL, *kvap, real_length,
6998 	    ddabh_flag, DDI_DMA_SLEEP, NULL, &cookie, &cookie_cnt)
6999 	    != DDI_DMA_MAPPED) {
7000 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "Failed to bind DMA");
7001 		ddi_dma_free_handle(dmah);
7002 		ddi_dma_mem_free(acch);
7003 		*dmah = NULL;
7004 		*acch = NULL;
7005 		return (B_FALSE);
7006 	}
7007 
7008 	if (cookie_cnt != 1) {
7009 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "Multiple cookies");
7010 		if (ddi_dma_unbind_handle(*dmah) != DDI_SUCCESS) {
7011 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "Condition "
7012 			    "failed at %s():%d", __func__, __LINE__);
7013 		}
7014 		ddi_dma_free_handle(dmah);
7015 		ddi_dma_mem_free(acch);
7016 		*dmah = NULL;
7017 		*acch = NULL;
7018 		return (B_FALSE);
7019 	}
7020 
7021 	*dma_addr = cookie.dmac_laddress;
7022 
7023 	return (B_TRUE);
7024 }
7025 
7026 /*
7027  * Flush requested queues for a particular target.  Called with statlock held
7028  */
7029 void
7030 pmcs_flush_target_queues(pmcs_hw_t *pwp, pmcs_xscsi_t *tgt, uint8_t queues)
7031 {
7032 	pmcs_cmd_t	*sp, *sp_next;
7033 	pmcwork_t	*pwrk;
7034 
7035 	ASSERT(pwp != NULL);
7036 	ASSERT(tgt != NULL);
7037 
7038 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, tgt,
7039 	    "%s: Flushing queues (%d) for target 0x%p", __func__,
7040 	    queues, (void *)tgt);
7041 
7042 	/*
7043 	 * Commands on the wait queue (or the special queue below) don't have
7044 	 * work structures associated with them.
7045 	 */
7046 	if (queues & PMCS_TGT_WAIT_QUEUE) {
7047 		mutex_enter(&tgt->wqlock);
7048 		while ((sp = STAILQ_FIRST(&tgt->wq)) != NULL) {
7049 			STAILQ_REMOVE(&tgt->wq, sp, pmcs_cmd, cmd_next);
7050 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, tgt,
7051 			    "%s: Removing cmd 0x%p from wq for target 0x%p",
7052 			    __func__, (void *)sp, (void *)tgt);
7053 			CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
7054 			CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
7055 			mutex_exit(&tgt->wqlock);
7056 			pmcs_dma_unload(pwp, sp);
7057 			mutex_enter(&pwp->cq_lock);
7058 			STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
7059 			mutex_exit(&pwp->cq_lock);
7060 			mutex_enter(&tgt->wqlock);
7061 		}
7062 		mutex_exit(&tgt->wqlock);
7063 	}
7064 
7065 	/*
7066 	 * Commands on the active queue will have work structures associated
7067 	 * with them.
7068 	 */
7069 	if (queues & PMCS_TGT_ACTIVE_QUEUE) {
7070 		mutex_enter(&tgt->aqlock);
7071 		sp = STAILQ_FIRST(&tgt->aq);
7072 		while (sp) {
7073 			sp_next = STAILQ_NEXT(sp, cmd_next);
7074 			pwrk = pmcs_tag2wp(pwp, sp->cmd_tag);
7075 
7076 			/*
7077 			 * If we don't find a work structure, it's because
7078 			 * the command is already complete.  If so, move on
7079 			 * to the next one.
7080 			 */
7081 			if (pwrk == NULL) {
7082 				pmcs_prt(pwp, PMCS_PRT_DEBUG1, tgt->phy, tgt,
7083 				    "%s: Not removing cmd 0x%p (htag 0x%x) "
7084 				    "from aq", __func__, (void *)sp,
7085 				    sp->cmd_tag);
7086 				sp = sp_next;
7087 				continue;
7088 			}
7089 
7090 			STAILQ_REMOVE(&tgt->aq, sp, pmcs_cmd, cmd_next);
7091 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, tgt->phy, tgt,
7092 			    "%s: Removing cmd 0x%p (htag 0x%x) from aq for "
7093 			    "target 0x%p", __func__, (void *)sp, sp->cmd_tag,
7094 			    (void *)tgt);
7095 			mutex_exit(&tgt->aqlock);
7096 			mutex_exit(&tgt->statlock);
7097 			/*
7098 			 * Mark the work structure as dead and complete it
7099 			 */
7100 			pwrk->dead = 1;
7101 			CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
7102 			CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
7103 			pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
7104 			pmcs_dma_unload(pwp, sp);
7105 			mutex_enter(&pwp->cq_lock);
7106 			STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
7107 			mutex_exit(&pwp->cq_lock);
7108 			mutex_enter(&tgt->aqlock);
7109 			mutex_enter(&tgt->statlock);
7110 			sp = sp_next;
7111 		}
7112 		mutex_exit(&tgt->aqlock);
7113 	}
7114 
7115 	if (queues & PMCS_TGT_SPECIAL_QUEUE) {
7116 		while ((sp = STAILQ_FIRST(&tgt->sq)) != NULL) {
7117 			STAILQ_REMOVE(&tgt->sq, sp, pmcs_cmd, cmd_next);
7118 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, tgt->phy, tgt,
7119 			    "%s: Removing cmd 0x%p from sq for target 0x%p",
7120 			    __func__, (void *)sp, (void *)tgt);
7121 			CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
7122 			CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
7123 			pmcs_dma_unload(pwp, sp);
7124 			mutex_enter(&pwp->cq_lock);
7125 			STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
7126 			mutex_exit(&pwp->cq_lock);
7127 		}
7128 	}
7129 }
7130 
7131 void
7132 pmcs_complete_work_impl(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
7133     size_t amt)
7134 {
7135 	switch (PMCS_TAG_TYPE(pwrk->htag)) {
7136 	case PMCS_TAG_TYPE_CBACK:
7137 	{
7138 		pmcs_cb_t callback = (pmcs_cb_t)pwrk->ptr;
7139 		(*callback)(pwp, pwrk, iomb);
7140 		break;
7141 	}
7142 	case PMCS_TAG_TYPE_WAIT:
7143 		if (pwrk->arg && iomb && amt) {
7144 			(void) memcpy(pwrk->arg, iomb, amt);
7145 		}
7146 		cv_signal(&pwrk->sleep_cv);
7147 		mutex_exit(&pwrk->lock);
7148 		break;
7149 	case PMCS_TAG_TYPE_NONE:
7150 #ifdef DEBUG
7151 		pmcs_check_iomb_status(pwp, iomb);
7152 #endif
7153 		pmcs_pwork(pwp, pwrk);
7154 		break;
7155 	default:
7156 		/*
7157 		 * We will leak a structure here if we don't know
7158 		 * what happened
7159 		 */
7160 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
7161 		    "%s: Unknown PMCS_TAG_TYPE (%x)",
7162 		    __func__, PMCS_TAG_TYPE(pwrk->htag));
7163 		break;
7164 	}
7165 }
7166 
7167 /*
7168  * Determine if iport still has targets. During detach(9E), if SCSA is
7169  * successfull in its guarantee of tran_tgt_free(9E) before detach(9E),
7170  * this should always return B_FALSE.
7171  */
7172 boolean_t
7173 pmcs_iport_has_targets(pmcs_hw_t *pwp, pmcs_iport_t *iport)
7174 {
7175 	pmcs_xscsi_t *xp;
7176 	int i;
7177 
7178 	mutex_enter(&pwp->lock);
7179 
7180 	if (!pwp->targets || !pwp->max_dev) {
7181 		mutex_exit(&pwp->lock);
7182 		return (B_FALSE);
7183 	}
7184 
7185 	for (i = 0; i < pwp->max_dev; i++) {
7186 		xp = pwp->targets[i];
7187 		if ((xp == NULL) || (xp->phy == NULL) ||
7188 		    (xp->phy->iport != iport)) {
7189 			continue;
7190 		}
7191 
7192 		mutex_exit(&pwp->lock);
7193 		return (B_TRUE);
7194 	}
7195 
7196 	mutex_exit(&pwp->lock);
7197 	return (B_FALSE);
7198 }
7199 
7200 /*
7201  * Called with softstate lock held
7202  */
7203 void
7204 pmcs_destroy_target(pmcs_xscsi_t *target)
7205 {
7206 	pmcs_hw_t *pwp = target->pwp;
7207 	pmcs_iport_t *iport;
7208 
7209 	ASSERT(pwp);
7210 	ASSERT(mutex_owned(&pwp->lock));
7211 
7212 	if (!target->ua) {
7213 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, target,
7214 		    "%s: target %p iport address is null",
7215 		    __func__, (void *)target);
7216 	}
7217 
7218 	iport = pmcs_get_iport_by_ua(pwp, target->ua);
7219 	if (iport == NULL) {
7220 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, target,
7221 		    "%s: no iport associated with tgt(0x%p)",
7222 		    __func__, (void *)target);
7223 		return;
7224 	}
7225 
7226 	pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, target,
7227 	    "%s: free target %p", __func__, (void *)target);
7228 	if (target->ua) {
7229 		strfree(target->ua);
7230 	}
7231 
7232 	mutex_destroy(&target->wqlock);
7233 	mutex_destroy(&target->aqlock);
7234 	mutex_destroy(&target->statlock);
7235 	cv_destroy(&target->reset_cv);
7236 	cv_destroy(&target->abort_cv);
7237 	ddi_soft_state_bystr_fini(&target->lun_sstate);
7238 	ddi_soft_state_bystr_free(iport->tgt_sstate, target->unit_address);
7239 	pmcs_rele_iport(iport);
7240 }
7241 
7242 /*
7243  * pmcs_lock_phy_impl
7244  *
7245  * This function is what does the actual work for pmcs_lock_phy.  It will
7246  * lock all PHYs from phyp down in a top-down fashion.
7247  *
7248  * Locking notes:
7249  * 1. level starts from 0 for the PHY ("parent") that's passed in.  It is
7250  * not a reflection of the actual level of the PHY in the SAS topology.
7251  * 2. If parent is an expander, then parent is locked along with all its
7252  * descendents.
7253  * 3. Expander subsidiary PHYs at level 0 are not locked.  It is the
7254  * responsibility of the caller to individually lock expander subsidiary PHYs
7255  * at level 0 if necessary.
7256  * 4. Siblings at level 0 are not traversed due to the possibility that we're
7257  * locking a PHY on the dead list.  The siblings could be pointing to invalid
7258  * PHYs.  We don't lock siblings at level 0 anyway.
7259  */
7260 static void
7261 pmcs_lock_phy_impl(pmcs_phy_t *phyp, int level)
7262 {
7263 	pmcs_phy_t *tphyp;
7264 
7265 	ASSERT((phyp->dtype == SAS) || (phyp->dtype == SATA) ||
7266 	    (phyp->dtype == EXPANDER) || (phyp->dtype == NOTHING));
7267 
7268 	/*
7269 	 * Start walking the PHYs.
7270 	 */
7271 	tphyp = phyp;
7272 	while (tphyp) {
7273 		/*
7274 		 * If we're at the top level, only lock ourselves.  For anything
7275 		 * at level > 0, traverse children while locking everything.
7276 		 */
7277 		if ((level > 0) || (tphyp == phyp)) {
7278 			pmcs_prt(tphyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, tphyp,
7279 			    NULL, "%s: PHY 0x%p parent 0x%p path %s lvl %d",
7280 			    __func__, (void *)tphyp, (void *)tphyp->parent,
7281 			    tphyp->path, level);
7282 			mutex_enter(&tphyp->phy_lock);
7283 
7284 			if (tphyp->children) {
7285 				pmcs_lock_phy_impl(tphyp->children, level + 1);
7286 			}
7287 		}
7288 
7289 		if (level == 0) {
7290 			return;
7291 		}
7292 
7293 		tphyp = tphyp->sibling;
7294 	}
7295 }
7296 
7297 /*
7298  * pmcs_lock_phy
7299  *
7300  * This function is responsible for locking a PHY and all its descendents
7301  */
7302 void
7303 pmcs_lock_phy(pmcs_phy_t *phyp)
7304 {
7305 #ifdef DEBUG
7306 	char *callername = NULL;
7307 	ulong_t off;
7308 
7309 	ASSERT(phyp != NULL);
7310 
7311 	callername = modgetsymname((uintptr_t)caller(), &off);
7312 
7313 	if (callername == NULL) {
7314 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7315 		    "%s: PHY 0x%p path %s caller: unknown", __func__,
7316 		    (void *)phyp, phyp->path);
7317 	} else {
7318 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7319 		    "%s: PHY 0x%p path %s caller: %s+%lx", __func__,
7320 		    (void *)phyp, phyp->path, callername, off);
7321 	}
7322 #else
7323 	pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7324 	    "%s: PHY 0x%p path %s", __func__, (void *)phyp, phyp->path);
7325 #endif
7326 	pmcs_lock_phy_impl(phyp, 0);
7327 }
7328 
7329 /*
7330  * pmcs_unlock_phy_impl
7331  *
7332  * Unlock all PHYs from phyp down in a bottom-up fashion.
7333  */
7334 static void
7335 pmcs_unlock_phy_impl(pmcs_phy_t *phyp, int level)
7336 {
7337 	pmcs_phy_t *phy_next;
7338 
7339 	ASSERT((phyp->dtype == SAS) || (phyp->dtype == SATA) ||
7340 	    (phyp->dtype == EXPANDER) || (phyp->dtype == NOTHING));
7341 
7342 	/*
7343 	 * Recurse down to the bottom PHYs
7344 	 */
7345 	if (level == 0) {
7346 		if (phyp->children) {
7347 			pmcs_unlock_phy_impl(phyp->children, level + 1);
7348 		}
7349 	} else {
7350 		phy_next = phyp;
7351 		while (phy_next) {
7352 			if (phy_next->children) {
7353 				pmcs_unlock_phy_impl(phy_next->children,
7354 				    level + 1);
7355 			}
7356 			phy_next = phy_next->sibling;
7357 		}
7358 	}
7359 
7360 	/*
7361 	 * Iterate through PHYs unlocking all at level > 0 as well the top PHY
7362 	 */
7363 	phy_next = phyp;
7364 	while (phy_next) {
7365 		if ((level > 0) || (phy_next == phyp)) {
7366 			pmcs_prt(phy_next->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
7367 			    phy_next, NULL,
7368 			    "%s: PHY 0x%p parent 0x%p path %s lvl %d",
7369 			    __func__, (void *)phy_next,
7370 			    (void *)phy_next->parent, phy_next->path, level);
7371 			mutex_exit(&phy_next->phy_lock);
7372 		}
7373 
7374 		if (level == 0) {
7375 			return;
7376 		}
7377 
7378 		phy_next = phy_next->sibling;
7379 	}
7380 }
7381 
7382 /*
7383  * pmcs_unlock_phy
7384  *
7385  * Unlock a PHY and all its descendents
7386  */
7387 void
7388 pmcs_unlock_phy(pmcs_phy_t *phyp)
7389 {
7390 #ifdef DEBUG
7391 	char *callername = NULL;
7392 	ulong_t off;
7393 
7394 	ASSERT(phyp != NULL);
7395 
7396 	callername = modgetsymname((uintptr_t)caller(), &off);
7397 
7398 	if (callername == NULL) {
7399 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7400 		    "%s: PHY 0x%p path %s caller: unknown", __func__,
7401 		    (void *)phyp, phyp->path);
7402 	} else {
7403 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7404 		    "%s: PHY 0x%p path %s caller: %s+%lx", __func__,
7405 		    (void *)phyp, phyp->path, callername, off);
7406 	}
7407 #else
7408 	pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING, phyp, NULL,
7409 	    "%s: PHY 0x%p path %s", __func__, (void *)phyp, phyp->path);
7410 #endif
7411 	pmcs_unlock_phy_impl(phyp, 0);
7412 }
7413 
7414 /*
7415  * pmcs_get_root_phy
7416  *
7417  * For a given phy pointer return its root phy.
7418  * This function must only be called during discovery in order to ensure that
7419  * the chain of PHYs from phyp up to the root PHY doesn't change.
7420  */
7421 pmcs_phy_t *
7422 pmcs_get_root_phy(pmcs_phy_t *phyp)
7423 {
7424 	ASSERT(phyp);
7425 
7426 	while (phyp) {
7427 		if (IS_ROOT_PHY(phyp)) {
7428 			break;
7429 		}
7430 		phyp = phyp->parent;
7431 	}
7432 
7433 	return (phyp);
7434 }
7435 
7436 /*
7437  * pmcs_free_dma_chunklist
7438  *
7439  * Free DMA S/G chunk list
7440  */
7441 void
7442 pmcs_free_dma_chunklist(pmcs_hw_t *pwp)
7443 {
7444 	pmcs_chunk_t	*pchunk;
7445 
7446 	while (pwp->dma_chunklist) {
7447 		pchunk = pwp->dma_chunklist;
7448 		pwp->dma_chunklist = pwp->dma_chunklist->next;
7449 		if (pchunk->dma_handle) {
7450 			if (ddi_dma_unbind_handle(pchunk->dma_handle) !=
7451 			    DDI_SUCCESS) {
7452 				pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
7453 				    "Condition failed at %s():%d",
7454 				    __func__, __LINE__);
7455 			}
7456 			ddi_dma_free_handle(&pchunk->dma_handle);
7457 			ddi_dma_mem_free(&pchunk->acc_handle);
7458 		}
7459 		kmem_free(pchunk, sizeof (pmcs_chunk_t));
7460 	}
7461 }
7462 
7463 /*ARGSUSED2*/
7464 int
7465 pmcs_phy_constructor(void *buf, void *arg, int kmflags)
7466 {
7467 	pmcs_hw_t *pwp = (pmcs_hw_t *)arg;
7468 	pmcs_phy_t *phyp = (pmcs_phy_t *)buf;
7469 
7470 	mutex_init(&phyp->phy_lock, NULL, MUTEX_DRIVER,
7471 	    DDI_INTR_PRI(pwp->intr_pri));
7472 	cv_init(&phyp->abort_all_cv, NULL, CV_DRIVER, NULL);
7473 	return (0);
7474 }
7475 
7476 /*ARGSUSED1*/
7477 void
7478 pmcs_phy_destructor(void *buf, void *arg)
7479 {
7480 	pmcs_phy_t *phyp = (pmcs_phy_t *)buf;
7481 
7482 	cv_destroy(&phyp->abort_all_cv);
7483 	mutex_destroy(&phyp->phy_lock);
7484 }
7485 
7486 /*
7487  * Free all PHYs from the kmem_cache starting at phyp as well as everything
7488  * on the dead_phys list.
7489  *
7490  * NOTE: This function does not free root PHYs as they are not allocated
7491  * from the kmem_cache.
7492  *
7493  * No PHY locks are acquired as this should only be called during DDI_DETACH
7494  * or soft reset (while pmcs interrupts are disabled).
7495  */
7496 void
7497 pmcs_free_all_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
7498 {
7499 	pmcs_phy_t *tphyp, *nphyp;
7500 
7501 	if (phyp == NULL) {
7502 		return;
7503 	}
7504 
7505 	tphyp = phyp;
7506 	while (tphyp) {
7507 		nphyp = tphyp->sibling;
7508 
7509 		if (tphyp->children) {
7510 			pmcs_free_all_phys(pwp, tphyp->children);
7511 			tphyp->children = NULL;
7512 		}
7513 		if (!IS_ROOT_PHY(tphyp)) {
7514 			kmem_cache_free(pwp->phy_cache, tphyp);
7515 		}
7516 
7517 		tphyp = nphyp;
7518 	}
7519 
7520 	tphyp = pwp->dead_phys;
7521 	while (tphyp) {
7522 		nphyp = tphyp->sibling;
7523 		kmem_cache_free(pwp->phy_cache, tphyp);
7524 		tphyp = nphyp;
7525 	}
7526 	pwp->dead_phys = NULL;
7527 }
7528 
7529 /*
7530  * Free a list of PHYs linked together by the sibling pointer back to the
7531  * kmem cache from whence they came.  This function does not recurse, so the
7532  * caller must ensure there are no children.
7533  */
7534 void
7535 pmcs_free_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
7536 {
7537 	pmcs_phy_t *next_phy;
7538 
7539 	while (phyp) {
7540 		next_phy = phyp->sibling;
7541 		ASSERT(!mutex_owned(&phyp->phy_lock));
7542 		kmem_cache_free(pwp->phy_cache, phyp);
7543 		phyp = next_phy;
7544 	}
7545 }
7546 
7547 /*
7548  * Make a copy of an existing PHY structure.  This is used primarily in
7549  * discovery to compare the contents of an existing PHY with what gets
7550  * reported back by an expander.
7551  *
7552  * This function must not be called from any context where sleeping is
7553  * not possible.
7554  *
7555  * The new PHY is returned unlocked.
7556  */
7557 static pmcs_phy_t *
7558 pmcs_clone_phy(pmcs_phy_t *orig_phy)
7559 {
7560 	pmcs_phy_t *local;
7561 
7562 	local = kmem_cache_alloc(orig_phy->pwp->phy_cache, KM_SLEEP);
7563 
7564 	/*
7565 	 * Go ahead and just copy everything...
7566 	 */
7567 	*local = *orig_phy;
7568 
7569 	/*
7570 	 * But the following must be set appropriately for this copy
7571 	 */
7572 	local->sibling = NULL;
7573 	local->children = NULL;
7574 	mutex_init(&local->phy_lock, NULL, MUTEX_DRIVER,
7575 	    DDI_INTR_PRI(orig_phy->pwp->intr_pri));
7576 
7577 	return (local);
7578 }
7579 
7580 int
7581 pmcs_check_acc_handle(ddi_acc_handle_t handle)
7582 {
7583 	ddi_fm_error_t de;
7584 
7585 	if (handle == NULL) {
7586 		return (DDI_FAILURE);
7587 	}
7588 	ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
7589 	return (de.fme_status);
7590 }
7591 
7592 int
7593 pmcs_check_dma_handle(ddi_dma_handle_t handle)
7594 {
7595 	ddi_fm_error_t de;
7596 
7597 	if (handle == NULL) {
7598 		return (DDI_FAILURE);
7599 	}
7600 	ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
7601 	return (de.fme_status);
7602 }
7603 
7604 
7605 void
7606 pmcs_fm_ereport(pmcs_hw_t *pwp, char *detail)
7607 {
7608 	uint64_t ena;
7609 	char buf[FM_MAX_CLASS];
7610 
7611 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
7612 	ena = fm_ena_generate(0, FM_ENA_FMT1);
7613 	if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities)) {
7614 		ddi_fm_ereport_post(pwp->dip, buf, ena, DDI_NOSLEEP,
7615 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
7616 	}
7617 }
7618 
7619 int
7620 pmcs_check_acc_dma_handle(pmcs_hw_t *pwp)
7621 {
7622 	pmcs_chunk_t *pchunk;
7623 	int i;
7624 
7625 	/* check all acc & dma handles allocated in attach */
7626 	if ((pmcs_check_acc_handle(pwp->pci_acc_handle) != DDI_SUCCESS) ||
7627 	    (pmcs_check_acc_handle(pwp->msg_acc_handle) != DDI_SUCCESS) ||
7628 	    (pmcs_check_acc_handle(pwp->top_acc_handle) != DDI_SUCCESS) ||
7629 	    (pmcs_check_acc_handle(pwp->mpi_acc_handle) != DDI_SUCCESS) ||
7630 	    (pmcs_check_acc_handle(pwp->gsm_acc_handle) != DDI_SUCCESS)) {
7631 		goto check_failed;
7632 	}
7633 
7634 	for (i = 0; i < PMCS_NIQ; i++) {
7635 		if ((pmcs_check_dma_handle(
7636 		    pwp->iqp_handles[i]) != DDI_SUCCESS) ||
7637 		    (pmcs_check_acc_handle(
7638 		    pwp->iqp_acchdls[i]) != DDI_SUCCESS)) {
7639 			goto check_failed;
7640 		}
7641 	}
7642 
7643 	for (i = 0; i < PMCS_NOQ; i++) {
7644 		if ((pmcs_check_dma_handle(
7645 		    pwp->oqp_handles[i]) != DDI_SUCCESS) ||
7646 		    (pmcs_check_acc_handle(
7647 		    pwp->oqp_acchdls[i]) != DDI_SUCCESS)) {
7648 			goto check_failed;
7649 		}
7650 	}
7651 
7652 	if ((pmcs_check_dma_handle(pwp->cip_handles) != DDI_SUCCESS) ||
7653 	    (pmcs_check_acc_handle(pwp->cip_acchdls) != DDI_SUCCESS)) {
7654 		goto check_failed;
7655 	}
7656 
7657 	if (pwp->fwlog &&
7658 	    ((pmcs_check_dma_handle(pwp->fwlog_hndl) != DDI_SUCCESS) ||
7659 	    (pmcs_check_acc_handle(pwp->fwlog_acchdl) != DDI_SUCCESS))) {
7660 		goto check_failed;
7661 	}
7662 
7663 	if (pwp->regdump_hndl && pwp->regdump_acchdl &&
7664 	    ((pmcs_check_dma_handle(pwp->regdump_hndl) != DDI_SUCCESS) ||
7665 	    (pmcs_check_acc_handle(pwp->regdump_acchdl)
7666 	    != DDI_SUCCESS))) {
7667 		goto check_failed;
7668 	}
7669 
7670 
7671 	pchunk = pwp->dma_chunklist;
7672 	while (pchunk) {
7673 		if ((pmcs_check_acc_handle(pchunk->acc_handle)
7674 		    != DDI_SUCCESS) ||
7675 		    (pmcs_check_dma_handle(pchunk->dma_handle)
7676 		    != DDI_SUCCESS)) {
7677 			goto check_failed;
7678 		}
7679 		pchunk = pchunk->next;
7680 	}
7681 
7682 	return (0);
7683 
7684 check_failed:
7685 
7686 	return (1);
7687 }
7688 
7689 /*
7690  * pmcs_handle_dead_phys
7691  *
7692  * If the PHY has no outstanding work associated with it, remove it from
7693  * the dead PHY list and free it.
7694  *
7695  * If pwp->ds_err_recovering or pwp->configuring is set, don't run.
7696  * This keeps routines that need to submit work to the chip from having to
7697  * hold PHY locks to ensure that PHYs don't disappear while they do their work.
7698  */
7699 void
7700 pmcs_handle_dead_phys(pmcs_hw_t *pwp)
7701 {
7702 	pmcs_phy_t *phyp, *nphyp, *pphyp;
7703 
7704 	mutex_enter(&pwp->lock);
7705 	mutex_enter(&pwp->config_lock);
7706 
7707 	if (pwp->configuring | pwp->ds_err_recovering) {
7708 		mutex_exit(&pwp->config_lock);
7709 		mutex_exit(&pwp->lock);
7710 		return;
7711 	}
7712 
7713 	/*
7714 	 * Check every PHY in the dead PHY list
7715 	 */
7716 	mutex_enter(&pwp->dead_phylist_lock);
7717 	phyp = pwp->dead_phys;
7718 	pphyp = NULL;	/* Set previous PHY to NULL */
7719 
7720 	while (phyp != NULL) {
7721 		pmcs_lock_phy(phyp);
7722 		ASSERT(phyp->dead);
7723 
7724 		nphyp = phyp->dead_next;
7725 
7726 		/*
7727 		 * Check for outstanding work
7728 		 */
7729 		if (phyp->ref_count > 0) {
7730 			pmcs_unlock_phy(phyp);
7731 			pphyp = phyp;	/* This PHY becomes "previous" */
7732 		} else if (phyp->target) {
7733 			pmcs_unlock_phy(phyp);
7734 			pmcs_prt(pwp, PMCS_PRT_DEBUG1, phyp, phyp->target,
7735 			    "%s: Not freeing PHY 0x%p: target 0x%p is not free",
7736 			    __func__, (void *)phyp, (void *)phyp->target);
7737 			pphyp = phyp;
7738 		} else {
7739 			/*
7740 			 * No outstanding work or target references. Remove it
7741 			 * from the list and free it
7742 			 */
7743 			pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, phyp->target,
7744 			    "%s: Freeing inactive dead PHY 0x%p @ %s "
7745 			    "target = 0x%p", __func__, (void *)phyp,
7746 			    phyp->path, (void *)phyp->target);
7747 			/*
7748 			 * If pphyp is NULL, then phyp was the head of the list,
7749 			 * so just reset the head to nphyp. Otherwise, the
7750 			 * previous PHY will now point to nphyp (the next PHY)
7751 			 */
7752 			if (pphyp == NULL) {
7753 				pwp->dead_phys = nphyp;
7754 			} else {
7755 				pphyp->dead_next = nphyp;
7756 			}
7757 			/*
7758 			 * If the target still points to this PHY, remove
7759 			 * that linkage now.
7760 			 */
7761 			if (phyp->target) {
7762 				mutex_enter(&phyp->target->statlock);
7763 				if (phyp->target->phy == phyp) {
7764 					phyp->target->phy = NULL;
7765 				}
7766 				mutex_exit(&phyp->target->statlock);
7767 			}
7768 			pmcs_unlock_phy(phyp);
7769 			kmem_cache_free(pwp->phy_cache, phyp);
7770 		}
7771 
7772 		phyp = nphyp;
7773 	}
7774 
7775 	mutex_exit(&pwp->dead_phylist_lock);
7776 	mutex_exit(&pwp->config_lock);
7777 	mutex_exit(&pwp->lock);
7778 }
7779 
7780 void
7781 pmcs_inc_phy_ref_count(pmcs_phy_t *phyp)
7782 {
7783 	atomic_inc_32(&phyp->ref_count);
7784 }
7785 
7786 void
7787 pmcs_dec_phy_ref_count(pmcs_phy_t *phyp)
7788 {
7789 	ASSERT(phyp->ref_count != 0);
7790 	atomic_dec_32(&phyp->ref_count);
7791 }
7792 
7793 /*
7794  * pmcs_reap_dead_phy
7795  *
7796  * This function is called from pmcs_new_tport when we have a PHY
7797  * without a target pointer.  It's possible in that case that this PHY
7798  * may have a "brother" on the dead_phys list.  That is, it may be the same as
7799  * this one but with a different root PHY number (e.g. pp05 vs. pp04).  If
7800  * that's the case, update the dead PHY and this new PHY.  If that's not the
7801  * case, we should get a tran_tgt_init on this after it's reported to SCSA.
7802  *
7803  * Called with PHY locked.
7804  */
7805 static void
7806 pmcs_reap_dead_phy(pmcs_phy_t *phyp)
7807 {
7808 	pmcs_hw_t *pwp = phyp->pwp;
7809 	pmcs_phy_t *ctmp;
7810 	pmcs_iport_t *iport_cmp;
7811 
7812 	ASSERT(mutex_owned(&phyp->phy_lock));
7813 
7814 	/*
7815 	 * Check the dead PHYs list
7816 	 */
7817 	mutex_enter(&pwp->dead_phylist_lock);
7818 	ctmp = pwp->dead_phys;
7819 	while (ctmp) {
7820 		/*
7821 		 * If the iport is NULL, compare against last_iport.
7822 		 */
7823 		if (ctmp->iport) {
7824 			iport_cmp = ctmp->iport;
7825 		} else {
7826 			iport_cmp = ctmp->last_iport;
7827 		}
7828 
7829 		if ((iport_cmp != phyp->iport) ||
7830 		    (memcmp((void *)&ctmp->sas_address[0],
7831 		    (void *)&phyp->sas_address[0], 8))) {
7832 			ctmp = ctmp->dead_next;
7833 			continue;
7834 		}
7835 
7836 		/*
7837 		 * Same SAS address on same iport.  Now check to see if
7838 		 * the PHY path is the same with the possible exception
7839 		 * of the root PHY number.
7840 		 * The "5" is the string length of "pp00."
7841 		 */
7842 		if ((strnlen(phyp->path, 5) >= 5) &&
7843 		    (strnlen(ctmp->path, 5) >= 5)) {
7844 			if (memcmp((void *)&phyp->path[5],
7845 			    (void *)&ctmp->path[5],
7846 			    strnlen(phyp->path, 32) - 5) == 0) {
7847 				break;
7848 			}
7849 		}
7850 
7851 		ctmp = ctmp->dead_next;
7852 	}
7853 	mutex_exit(&pwp->dead_phylist_lock);
7854 
7855 	/*
7856 	 * Found a match.  Remove the target linkage and drop the
7857 	 * ref count on the old PHY.  Then, increment the ref count
7858 	 * on the new PHY to compensate.
7859 	 */
7860 	if (ctmp) {
7861 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, ctmp, NULL,
7862 		    "%s: Found match in dead PHY list (0x%p) for new PHY %s",
7863 		    __func__, (void *)ctmp, phyp->path);
7864 		/*
7865 		 * If there is a pointer to the target in the dead PHY, move
7866 		 * all reference counts to the new PHY.
7867 		 */
7868 		if (ctmp->target) {
7869 			mutex_enter(&ctmp->target->statlock);
7870 			phyp->target = ctmp->target;
7871 
7872 			while (ctmp->ref_count != 0) {
7873 				pmcs_inc_phy_ref_count(phyp);
7874 				pmcs_dec_phy_ref_count(ctmp);
7875 			}
7876 			/*
7877 			 * Update the target's linkage as well
7878 			 */
7879 			phyp->target->phy = phyp;
7880 			phyp->target->dtype = phyp->dtype;
7881 			ctmp->target = NULL;
7882 			mutex_exit(&phyp->target->statlock);
7883 		}
7884 	}
7885 }
7886 
7887 /*
7888  * Called with iport lock held
7889  */
7890 void
7891 pmcs_add_phy_to_iport(pmcs_iport_t *iport, pmcs_phy_t *phyp)
7892 {
7893 	ASSERT(mutex_owned(&iport->lock));
7894 	ASSERT(phyp);
7895 	ASSERT(!list_link_active(&phyp->list_node));
7896 	iport->nphy++;
7897 	list_insert_tail(&iport->phys, phyp);
7898 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
7899 	    &iport->nphy);
7900 	mutex_enter(&iport->refcnt_lock);
7901 	iport->refcnt++;
7902 	mutex_exit(&iport->refcnt_lock);
7903 }
7904 
7905 /*
7906  * Called with the iport lock held
7907  */
7908 void
7909 pmcs_remove_phy_from_iport(pmcs_iport_t *iport, pmcs_phy_t *phyp)
7910 {
7911 	pmcs_phy_t *pptr, *next_pptr;
7912 
7913 	ASSERT(mutex_owned(&iport->lock));
7914 
7915 	/*
7916 	 * If phyp is NULL, remove all PHYs from the iport
7917 	 */
7918 	if (phyp == NULL) {
7919 		for (pptr = list_head(&iport->phys); pptr != NULL;
7920 		    pptr = next_pptr) {
7921 			next_pptr = list_next(&iport->phys, pptr);
7922 			mutex_enter(&pptr->phy_lock);
7923 			pptr->iport = NULL;
7924 			pmcs_update_phy_pm_props(pptr, pptr->att_port_pm_tmp,
7925 			    pptr->tgt_port_pm_tmp, B_FALSE);
7926 			mutex_exit(&pptr->phy_lock);
7927 			pmcs_rele_iport(iport);
7928 			list_remove(&iport->phys, pptr);
7929 			pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32,
7930 			    PMCS_NUM_PHYS, &iport->nphy);
7931 		}
7932 		iport->nphy = 0;
7933 		return;
7934 	}
7935 
7936 	ASSERT(phyp);
7937 	ASSERT(iport->nphy > 0);
7938 	ASSERT(list_link_active(&phyp->list_node));
7939 	iport->nphy--;
7940 	list_remove(&iport->phys, phyp);
7941 	pmcs_update_phy_pm_props(phyp, phyp->att_port_pm_tmp,
7942 	    phyp->tgt_port_pm_tmp, B_FALSE);
7943 	pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
7944 	    &iport->nphy);
7945 	pmcs_rele_iport(iport);
7946 }
7947 
7948 /*
7949  * This function checks to see if the target pointed to by phyp is still
7950  * correct.  This is done by comparing the target's unit address with the
7951  * SAS address in phyp.
7952  *
7953  * Called with PHY locked and target statlock held
7954  */
7955 static boolean_t
7956 pmcs_phy_target_match(pmcs_phy_t *phyp)
7957 {
7958 	uint64_t wwn;
7959 	char unit_address[PMCS_MAX_UA_SIZE];
7960 	boolean_t rval = B_FALSE;
7961 
7962 	ASSERT(phyp);
7963 	ASSERT(phyp->target);
7964 	ASSERT(mutex_owned(&phyp->phy_lock));
7965 	ASSERT(mutex_owned(&phyp->target->statlock));
7966 
7967 	wwn = pmcs_barray2wwn(phyp->sas_address);
7968 	(void) scsi_wwn_to_wwnstr(wwn, 1, unit_address);
7969 
7970 	if (memcmp((void *)unit_address, (void *)phyp->target->unit_address,
7971 	    strnlen(phyp->target->unit_address, PMCS_MAX_UA_SIZE)) == 0) {
7972 		rval = B_TRUE;
7973 	}
7974 
7975 	return (rval);
7976 }
7977 /*
7978  * Commands used to serialize SMP requests.
7979  *
7980  * The SPC only allows 2 SMP commands per SMP target: 1 cmd pending and 1 cmd
7981  * queued for the same SMP target. If a third SMP cmd is sent to the SPC for an
7982  * SMP target that already has a SMP cmd pending and one queued, then the
7983  * SPC responds with the ERROR_INTERNAL_SMP_RESOURCE response.
7984  *
7985  * Additionally, the SPC has an 8 entry deep cmd queue and the number of SMP
7986  * cmds that can be queued is controlled by the PORT_CONTROL IOMB. The
7987  * SPC default is 1 SMP command/port (iport).  These 2 queued SMP cmds would
7988  * have to be for different SMP targets.  The INTERNAL_SMP_RESOURCE error will
7989  * also be returned if a 2nd SMP cmd is sent to the controller when there is
7990  * already 1 SMP cmd queued for that port or if a 3rd SMP cmd is sent to the
7991  * queue if there are already 2 queued SMP cmds.
7992  */
7993 void
7994 pmcs_smp_acquire(pmcs_iport_t *iport)
7995 {
7996 	if (iport == NULL) {
7997 		return;
7998 	}
7999 
8000 	mutex_enter(&iport->smp_lock);
8001 	while (iport->smp_active) {
8002 		pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
8003 		    "%s: SMP is active on thread 0x%p, waiting", __func__,
8004 		    (void *)iport->smp_active_thread);
8005 		cv_wait(&iport->smp_cv, &iport->smp_lock);
8006 	}
8007 	iport->smp_active = B_TRUE;
8008 	iport->smp_active_thread = curthread;
8009 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG3, NULL, NULL,
8010 	    "%s: SMP acquired by thread 0x%p", __func__,
8011 	    (void *)iport->smp_active_thread);
8012 	mutex_exit(&iport->smp_lock);
8013 }
8014 
8015 void
8016 pmcs_smp_release(pmcs_iport_t *iport)
8017 {
8018 	if (iport == NULL) {
8019 		return;
8020 	}
8021 
8022 	mutex_enter(&iport->smp_lock);
8023 	pmcs_prt(iport->pwp, PMCS_PRT_DEBUG3, NULL, NULL,
8024 	    "%s: SMP released by thread 0x%p", __func__, (void *)curthread);
8025 	iport->smp_active = B_FALSE;
8026 	iport->smp_active_thread = NULL;
8027 	cv_signal(&iport->smp_cv);
8028 	mutex_exit(&iport->smp_lock);
8029 }
8030 
8031 /*
8032  * Update a PHY's attached-port-pm and target-port-pm properties
8033  *
8034  * phyp: PHY whose properties are to be updated
8035  *
8036  * att_bv: Bit value of the attached-port-pm property to be updated in the
8037  * 64-bit holding area for the PHY.
8038  *
8039  * tgt_bv: Bit value of the target-port-pm property to update in the 64-bit
8040  * holding area for the PHY.
8041  *
8042  * prop_add_val: If TRUE, we're adding bits into the property value.
8043  * Otherwise, we're taking them out.  Either way, the properties for this
8044  * PHY will be updated.
8045  */
8046 void
8047 pmcs_update_phy_pm_props(pmcs_phy_t *phyp, uint64_t att_bv, uint64_t tgt_bv,
8048     boolean_t prop_add_val)
8049 {
8050 	if (prop_add_val) {
8051 		/*
8052 		 * If the values are currently 0, then we're setting the
8053 		 * phymask for just this PHY as well.
8054 		 */
8055 		if (phyp->att_port_pm_tmp == 0) {
8056 			phyp->att_port_pm = att_bv;
8057 			phyp->tgt_port_pm = tgt_bv;
8058 		}
8059 		phyp->att_port_pm_tmp |= att_bv;
8060 		phyp->tgt_port_pm_tmp |= tgt_bv;
8061 		(void) snprintf(phyp->att_port_pm_str, PMCS_PM_MAX_NAMELEN,
8062 		    "%"PRIx64, phyp->att_port_pm_tmp);
8063 		(void) snprintf(phyp->tgt_port_pm_str, PMCS_PM_MAX_NAMELEN,
8064 		    "%"PRIx64, phyp->tgt_port_pm_tmp);
8065 	} else {
8066 		phyp->att_port_pm_tmp &= ~att_bv;
8067 		phyp->tgt_port_pm_tmp &= ~tgt_bv;
8068 		if (phyp->att_port_pm_tmp) {
8069 			(void) snprintf(phyp->att_port_pm_str,
8070 			    PMCS_PM_MAX_NAMELEN, "%"PRIx64,
8071 			    phyp->att_port_pm_tmp);
8072 		} else {
8073 			phyp->att_port_pm_str[0] = '\0';
8074 			phyp->att_port_pm = 0;
8075 		}
8076 		if (phyp->tgt_port_pm_tmp) {
8077 			(void) snprintf(phyp->tgt_port_pm_str,
8078 			    PMCS_PM_MAX_NAMELEN, "%"PRIx64,
8079 			    phyp->tgt_port_pm_tmp);
8080 		} else {
8081 			phyp->tgt_port_pm_str[0] = '\0';
8082 			phyp->tgt_port_pm = 0;
8083 		}
8084 	}
8085 
8086 	if (phyp->target == NULL) {
8087 		return;
8088 	}
8089 
8090 	mutex_enter(&phyp->target->statlock);
8091 	if (!list_is_empty(&phyp->target->lun_list)) {
8092 		pmcs_lun_t *lunp;
8093 
8094 		lunp = list_head(&phyp->target->lun_list);
8095 		while (lunp) {
8096 			(void) scsi_device_prop_update_string(lunp->sd,
8097 			    SCSI_DEVICE_PROP_PATH,
8098 			    SCSI_ADDR_PROP_ATTACHED_PORT_PM,
8099 			    phyp->att_port_pm_str);
8100 			(void) scsi_device_prop_update_string(lunp->sd,
8101 			    SCSI_DEVICE_PROP_PATH,
8102 			    SCSI_ADDR_PROP_TARGET_PORT_PM,
8103 			    phyp->tgt_port_pm_str);
8104 			lunp = list_next(&phyp->target->lun_list, lunp);
8105 		}
8106 	} else if (phyp->target->smpd) {
8107 		(void) smp_device_prop_update_string(phyp->target->smpd,
8108 		    SCSI_ADDR_PROP_ATTACHED_PORT_PM,
8109 		    phyp->att_port_pm_str);
8110 		(void) smp_device_prop_update_string(phyp->target->smpd,
8111 		    SCSI_ADDR_PROP_TARGET_PORT_PM,
8112 		    phyp->tgt_port_pm_str);
8113 	}
8114 	mutex_exit(&phyp->target->statlock);
8115 }
8116 
8117 /* ARGSUSED */
8118 void
8119 pmcs_deregister_device_work(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
8120 {
8121 	pmcs_phy_t	*pptr;
8122 
8123 	for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
8124 		pmcs_lock_phy(pptr);
8125 		if (pptr->deregister_wait) {
8126 			pmcs_deregister_device(pwp, pptr);
8127 		}
8128 		pmcs_unlock_phy(pptr);
8129 	}
8130 }
8131 
8132 /*
8133  * pmcs_iport_active
8134  *
8135  * Mark this iport as active.  Called with the iport lock held.
8136  */
8137 static void
8138 pmcs_iport_active(pmcs_iport_t *iport)
8139 {
8140 	ASSERT(mutex_owned(&iport->lock));
8141 
8142 	iport->ua_state = UA_ACTIVE;
8143 	iport->smp_active = B_FALSE;
8144 	iport->smp_active_thread = NULL;
8145 }
8146 
8147 /* ARGSUSED */
8148 static void
8149 pmcs_tgtmap_activate_cb(void *tgtmap_priv, char *tgt_addr,
8150     scsi_tgtmap_tgt_type_t tgt_type, void **tgt_privp)
8151 {
8152 	pmcs_iport_t *iport = (pmcs_iport_t *)tgtmap_priv;
8153 	pmcs_hw_t *pwp = iport->pwp;
8154 	pmcs_xscsi_t *target;
8155 
8156 	/*
8157 	 * Look up the target.  If there is one, and it doesn't have a PHY
8158 	 * pointer, re-establish that linkage here.
8159 	 */
8160 	mutex_enter(&pwp->lock);
8161 	target = pmcs_get_target(iport, tgt_addr, B_FALSE);
8162 	mutex_exit(&pwp->lock);
8163 
8164 	/*
8165 	 * If we got a target, it will now have a PHY pointer and the PHY
8166 	 * will point to the target.  The PHY will be locked, so we'll need
8167 	 * to unlock it.
8168 	 */
8169 	if (target) {
8170 		pmcs_unlock_phy(target->phy);
8171 	}
8172 
8173 	/*
8174 	 * Update config_restart_time so we don't try to restart discovery
8175 	 * while enumeration is still in progress.
8176 	 */
8177 	mutex_enter(&pwp->config_lock);
8178 	pwp->config_restart_time = ddi_get_lbolt() +
8179 	    drv_usectohz(PMCS_REDISCOVERY_DELAY);
8180 	mutex_exit(&pwp->config_lock);
8181 }
8182 
8183 /* ARGSUSED */
8184 static boolean_t
8185 pmcs_tgtmap_deactivate_cb(void *tgtmap_priv, char *tgt_addr,
8186     scsi_tgtmap_tgt_type_t tgt_type, void *tgt_priv,
8187     scsi_tgtmap_deact_rsn_t tgt_deact_rsn)
8188 {
8189 	pmcs_iport_t *iport = (pmcs_iport_t *)tgtmap_priv;
8190 	pmcs_phy_t *phyp;
8191 	boolean_t rediscover = B_FALSE;
8192 
8193 	ASSERT(iport);
8194 
8195 	phyp = pmcs_find_phy_by_sas_address(iport->pwp, iport, NULL, tgt_addr);
8196 	if (phyp == NULL) {
8197 		pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
8198 		    "%s: Couldn't find PHY at %s", __func__, tgt_addr);
8199 		return (rediscover);
8200 	}
8201 	/* phyp is locked */
8202 
8203 	if (!phyp->reenumerate && phyp->configured) {
8204 		pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_CONFIG, phyp, phyp->target,
8205 		    "%s: PHY @ %s is configured... re-enumerate", __func__,
8206 		    tgt_addr);
8207 		phyp->reenumerate = 1;
8208 	}
8209 
8210 	/*
8211 	 * Check to see if reenumerate is set, and if so, if we've reached our
8212 	 * maximum number of retries.
8213 	 */
8214 	if (phyp->reenumerate) {
8215 		if (phyp->enum_attempts == PMCS_MAX_REENUMERATE) {
8216 			pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_CONFIG, phyp,
8217 			    phyp->target,
8218 			    "%s: No more enumeration attempts for %s", __func__,
8219 			    tgt_addr);
8220 		} else {
8221 			pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_CONFIG, phyp,
8222 			    phyp->target, "%s: Re-attempt enumeration for %s",
8223 			    __func__, tgt_addr);
8224 			++phyp->enum_attempts;
8225 			rediscover = B_TRUE;
8226 		}
8227 
8228 		phyp->reenumerate = 0;
8229 	}
8230 
8231 	pmcs_unlock_phy(phyp);
8232 
8233 	mutex_enter(&iport->pwp->config_lock);
8234 	iport->pwp->config_restart_time = ddi_get_lbolt() +
8235 	    drv_usectohz(PMCS_REDISCOVERY_DELAY);
8236 	if (rediscover) {
8237 		iport->pwp->config_restart = B_TRUE;
8238 	} else if (iport->pwp->config_restart == B_TRUE) {
8239 		/*
8240 		 * If we aren't asking for rediscovery because of this PHY,
8241 		 * check to see if we're already asking for it on behalf of
8242 		 * some other PHY.  If so, we'll want to return TRUE, so reset
8243 		 * "rediscover" here.
8244 		 */
8245 		rediscover = B_TRUE;
8246 	}
8247 
8248 	mutex_exit(&iport->pwp->config_lock);
8249 
8250 	return (rediscover);
8251 }
8252 
8253 void
8254 pmcs_status_disposition(pmcs_phy_t *phyp, uint32_t status)
8255 {
8256 	ASSERT(phyp);
8257 	ASSERT(!mutex_owned(&phyp->phy_lock));
8258 
8259 	if (phyp == NULL) {
8260 		return;
8261 	}
8262 
8263 	pmcs_lock_phy(phyp);
8264 
8265 	/*
8266 	 * XXX: Do we need to call this function from an SSP_EVENT?
8267 	 */
8268 
8269 	switch (status) {
8270 	case PMCOUT_STATUS_NO_DEVICE:
8271 	case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
8272 	case PMCOUT_STATUS_XFER_ERR_BREAK:
8273 	case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
8274 	case PMCOUT_STATUS_OPEN_CNX_PROTOCOL_NOT_SUPPORTED:
8275 	case PMCOUT_STATUS_OPEN_CNX_ERROR_ZONE_VIOLATION:
8276 	case PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK:
8277 	case PMCOUT_STATUS_OPENCNX_ERROR_BAD_DESTINATION:
8278 	case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
8279 	case PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
8280 	case PMCOUT_STATUS_OPEN_CNX_ERROR_WRONG_DESTINATION:
8281 	case PMCOUT_STATUS_OPEN_CNX_ERROR_UNKNOWN_ERROR:
8282 	case PMCOUT_STATUS_IO_XFER_ERROR_NAK_RECEIVED:
8283 	case PMCOUT_STATUS_XFER_ERROR_RX_FRAME:
8284 	case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
8285 	case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
8286 	case PMCOUT_STATUS_IO_PORT_IN_RESET:
8287 	case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL:
8288 	case PMCOUT_STATUS_IO_DS_IN_RECOVERY:
8289 	case PMCOUT_STATUS_IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
8290 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG, phyp, phyp->target,
8291 		    "%s: status = 0x%x for " SAS_ADDR_FMT ", reenumerate",
8292 		    __func__, status, SAS_ADDR_PRT(phyp->sas_address));
8293 		phyp->reenumerate = 1;
8294 		break;
8295 
8296 	default:
8297 		pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG, phyp, phyp->target,
8298 		    "%s: status = 0x%x for " SAS_ADDR_FMT ", no reenumeration",
8299 		    __func__, status, SAS_ADDR_PRT(phyp->sas_address));
8300 		break;
8301 	}
8302 
8303 	pmcs_unlock_phy(phyp);
8304 }
8305 
8306 /*
8307  * Add the list of PHYs pointed to by phyp to the dead_phys_list
8308  *
8309  * Called with all PHYs in the list locked
8310  */
8311 static void
8312 pmcs_add_dead_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
8313 {
8314 	mutex_enter(&pwp->dead_phylist_lock);
8315 	while (phyp) {
8316 		pmcs_phy_t *nxt = phyp->sibling;
8317 		ASSERT(phyp->dead);
8318 		pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, NULL,
8319 		    "%s: dead PHY 0x%p (%s) (ref_count %d)", __func__,
8320 		    (void *)phyp, phyp->path, phyp->ref_count);
8321 		/*
8322 		 * Put this PHY on the dead PHY list for the watchdog to
8323 		 * clean up after any outstanding work has completed.
8324 		 */
8325 		phyp->dead_next = pwp->dead_phys;
8326 		pwp->dead_phys = phyp;
8327 		pmcs_unlock_phy(phyp);
8328 		phyp = nxt;
8329 	}
8330 	mutex_exit(&pwp->dead_phylist_lock);
8331 }
8332 
8333 static void
8334 pmcs_get_fw_version(pmcs_hw_t *pwp)
8335 {
8336 	uint32_t ila_len, ver_hi, ver_lo;
8337 	uint8_t ila_ver_string[9], img_flag;
8338 	char uc, *ucp = &uc;
8339 	unsigned long ila_ver;
8340 	uint64_t ver_hilo;
8341 
8342 	/* Firmware version is easy. */
8343 	pwp->fw = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FW);
8344 
8345 	/*
8346 	 * Get the image size (2nd to last dword)
8347 	 * NOTE: The GSM registers are mapped little-endian, but the data
8348 	 * on the flash is actually big-endian, so we need to swap these values
8349 	 * regardless of which platform we're on.
8350 	 */
8351 	ila_len = BSWAP_32(pmcs_rd_gsm_reg(pwp, GSM_FLASH_BASE_UPPER,
8352 	    GSM_FLASH_BASE + GSM_SM_BLKSZ - (2 << 2)));
8353 	if (ila_len > 65535) {
8354 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
8355 		    "%s: Invalid ILA image size (0x%x)?", __func__, ila_len);
8356 		return;
8357 	}
8358 
8359 	/*
8360 	 * The numeric version is at ila_len - PMCS_ILA_VER_OFFSET
8361 	 */
8362 	ver_hi = BSWAP_32(pmcs_rd_gsm_reg(pwp, GSM_FLASH_BASE_UPPER,
8363 	    GSM_FLASH_BASE + ila_len - PMCS_ILA_VER_OFFSET));
8364 	ver_lo = BSWAP_32(pmcs_rd_gsm_reg(pwp, GSM_FLASH_BASE_UPPER,
8365 	    GSM_FLASH_BASE + ila_len - PMCS_ILA_VER_OFFSET + 4));
8366 	ver_hilo = BE_64(((uint64_t)ver_hi << 32) | ver_lo);
8367 	bcopy((const void *)&ver_hilo, &ila_ver_string[0], 8);
8368 	ila_ver_string[8] = '\0';
8369 
8370 	(void) ddi_strtoul((const char *)ila_ver_string, &ucp, 16, &ila_ver);
8371 	pwp->ila_ver = (int)(ila_ver & 0xffffffff);
8372 
8373 	img_flag = (BSWAP_32(pmcs_rd_gsm_reg(pwp, GSM_FLASH_BASE_UPPER,
8374 	    GSM_FLASH_IMG_FLAGS)) & 0xff000000) >> 24;
8375 	if (img_flag & PMCS_IMG_FLAG_A) {
8376 		pwp->fw_active_img = 1;
8377 	} else {
8378 		pwp->fw_active_img = 0;
8379 	}
8380 }
8381