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