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