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