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