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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file contains firmware log routines.
28  */
29 
30 #include <sys/scsi/adapters/pmcs/pmcs.h>
31 
32 static int pmcs_dump_ioqs(pmcs_hw_t *, caddr_t, uint32_t);
33 static int pmcs_dump_spc_ver(pmcs_hw_t *, caddr_t, uint32_t);
34 static int pmcs_dump_mpi_table(pmcs_hw_t *, caddr_t, uint32_t);
35 static int pmcs_dump_gsm_conf(pmcs_hw_t *, caddr_t, uint32_t);
36 static int pmcs_dump_pcie_conf(pmcs_hw_t *, caddr_t, uint32_t);
37 static uint32_t pmcs_get_axil(pmcs_hw_t *);
38 static boolean_t pmcs_shift_axil(pmcs_hw_t *, uint32_t);
39 static void pmcs_restore_axil(pmcs_hw_t *, uint32_t);
40 static int pmcs_dump_gsm(pmcs_hw_t *, caddr_t, uint32_t);
41 static int pmcs_dump_fwlog(pmcs_hw_t *, caddr_t, uint32_t);
42 
43 /*
44  * Dump internal registers. Used after a firmware crash.
45  * Here dump various registers for firmware forensics,
46  * including MPI, GSM configuration, firmware log, IO Queues etc.
47  */
48 void
49 pmcs_register_dump_int(pmcs_hw_t *pwp)
50 {
51 	int n = 0;
52 	uint32_t size_left = 0;
53 	uint8_t slice = 0;
54 	caddr_t buf = NULL;
55 
56 	pmcs_prt(pwp, PMCS_PRT_DEBUG, "pmcs%d: Internal register dump",
57 	    ddi_get_instance(pwp->dip));
58 	ASSERT(mutex_owned(&pwp->lock));
59 
60 	if (pwp->regdumpp == NULL) {
61 		pwp->regdumpp =
62 		    kmem_zalloc(PMCS_REG_DUMP_SIZE, KM_NOSLEEP);
63 		if (pwp->regdumpp == NULL) {
64 			pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: register"
65 			    " dump memory not allocated", __func__);
66 			return;
67 		}
68 	}
69 	buf = pwp->regdumpp;
70 	size_left = PMCS_REG_DUMP_SIZE - 1;
71 
72 	n = pmcs_dump_spc_ver(pwp, buf, size_left);
73 	ASSERT(size_left >= n);
74 	buf += n; size_left -= n;
75 	n = pmcs_dump_gsm_conf(pwp, buf, size_left);
76 	ASSERT(size_left >= n);
77 	buf += n; size_left -= n;
78 	n = pmcs_dump_pcie_conf(pwp, buf, size_left);
79 	ASSERT(size_left >= n);
80 	buf += n; size_left -= n;
81 	n = pmcs_dump_mpi_table(pwp, buf, size_left);
82 	ASSERT(size_left >= n);
83 	buf += n; size_left -= n;
84 	n = pmcs_dump_ioqs(pwp, buf, size_left);
85 	ASSERT(size_left >= n);
86 	buf += n; size_left -= n;
87 
88 	mutex_exit(&pwp->lock);
89 	slice = (PMCS_REGISTER_DUMP_FLASH_SIZE / PMCS_FLASH_CHUNK_SIZE);
90 	n = snprintf(buf, size_left, "\nDump AAP1 register: \n"
91 	    "-----------------\n");
92 	ASSERT(size_left >= n);
93 	buf += n; size_left -= n;
94 	for (uint8_t j = 0; j < slice; j++) {
95 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
96 		    PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
97 		    buf, size_left);
98 		if (n == PMCS_FLASH_CHUNK_SIZE) {
99 			ASSERT(size_left >= n);
100 			buf += n; size_left -= n;
101 		} else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
102 			ASSERT(size_left >= n);
103 			buf += n; size_left -= n;
104 			break;
105 		} else if (n == 0) {
106 			n = snprintf(buf, size_left, "AAP1: Content of "
107 			    "register dump on flash is NULL\n");
108 			ASSERT(size_left >= n);
109 			buf += n; size_left -= n;
110 			break;
111 		} else {
112 			n = snprintf(buf, size_left,
113 			    "AAP1: Unable to obtain internal register dump\n");
114 			ASSERT(size_left >= n);
115 			buf += n; size_left -= n;
116 			break;
117 		}
118 
119 	}
120 
121 	n = snprintf(buf, size_left, "\nDump IOP register: \n"
122 	    "-----------------\n");
123 	ASSERT(size_left >= n);
124 	buf += n; size_left -= n;
125 	for (uint8_t j = 0; j < slice; j++) {
126 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
127 		    PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
128 		    buf, size_left);
129 		if (n == PMCS_FLASH_CHUNK_SIZE) {
130 			ASSERT(size_left >= n);
131 			buf += n; size_left -= n;
132 		} else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
133 			ASSERT(size_left >= n);
134 			buf += n; size_left -= n;
135 			break;
136 		} else if (n == 0) {
137 			n = snprintf(buf, size_left,
138 			    "IOP: Content of internal register dump is NULL\n");
139 			ASSERT(size_left >= n);
140 			buf += n; size_left -= n;
141 			break;
142 		} else {
143 			n = snprintf(buf, size_left,
144 			    "IOP: Unable to obtain internal register dump\n");
145 			ASSERT(size_left >= n);
146 			buf += n; size_left -= n;
147 			break;
148 		}
149 
150 	}
151 
152 	n = snprintf(buf, size_left, "\nDump AAP1 event log: \n"
153 	    "-----------------\n");
154 	ASSERT(size_left >= n);
155 	buf += n; size_left -= n;
156 	for (uint8_t j = 0; j < slice; j++) {
157 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
158 		    PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
159 		    buf, size_left);
160 		if (n > 0) {
161 			ASSERT(size_left >= n);
162 			buf += n; size_left -= n;
163 		} else {
164 			n = snprintf(buf, size_left,
165 			    "AAP1: Unable to obtain event log on flash\n");
166 			ASSERT(size_left >= n);
167 			buf += n; size_left -= n;
168 			break;
169 		}
170 	}
171 
172 	n = snprintf(buf, size_left, "\nDump IOP event log: \n"
173 	    "-----------------\n");
174 	ASSERT(size_left >= n);
175 	buf += n; size_left -= n;
176 	for (uint8_t j = 0; j < slice; j++) {
177 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
178 		    PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
179 		    buf, size_left);
180 		if (n > 0) {
181 			ASSERT(size_left >= n);
182 			buf += n; size_left -= n;
183 		} else {
184 			n = snprintf(buf, size_left,
185 			    "IOP: Unable to obtain event log dump\n");
186 			ASSERT(size_left >= n);
187 			buf += n; size_left -= n;
188 			break;
189 		}
190 	}
191 	mutex_enter(&pwp->lock);
192 
193 	n = snprintf(buf, size_left, "\nDump firmware log: \n"
194 	    "-----------------\n");
195 	ASSERT(size_left >= n);
196 	buf += n; size_left -= n;
197 
198 	n = pmcs_dump_fwlog(pwp, buf, size_left);
199 
200 	ASSERT(size_left >= n);
201 	buf += n; size_left -= n;
202 	n = snprintf(buf, size_left, "-----------------\n"
203 	    "\n------------ Dump internal registers end  -------------\n");
204 	ASSERT(size_left >= n);
205 	buf += n; size_left -= n;
206 
207 	n = pmcs_dump_gsm(pwp, buf, size_left);
208 	ASSERT(size_left >= n);
209 	buf += n; size_left -= n;
210 }
211 
212 static int
213 pmcs_dump_fwlog(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
214 {
215 	pmcs_fw_event_hdr_t *evl_hdr;
216 	int n = 0, retries = 0;
217 	uint32_t evlog_latest_idx;
218 	boolean_t log_is_current = B_FALSE;
219 
220 	if (pwp->fwlogp == NULL) {
221 		n = snprintf(buf, size_left, "\nFirmware logging "
222 		    "not enabled\n");
223 		return (n);
224 	}
225 
226 	/*
227 	 * First, check to make sure all entries have been DMAed to the
228 	 * log buffer.
229 	 *
230 	 * We'll wait the required 50ms, but if the latest entry keeps
231 	 * changing, we'll only retry twice
232 	 */
233 	evl_hdr = (pmcs_fw_event_hdr_t *)pwp->fwlogp;
234 	evlog_latest_idx = evl_hdr->fw_el_latest_idx;
235 
236 	while ((log_is_current == B_FALSE) && (retries < 3)) {
237 		drv_usecwait(50 * 1000);
238 		if (evl_hdr->fw_el_latest_idx == evlog_latest_idx) {
239 			log_is_current = B_TRUE;
240 		} else {
241 			++retries;
242 			pmcs_prt(pwp, PMCS_PRT_DEBUG,
243 			    "%s: event log is still being updated... waiting",
244 			    __func__);
245 			evlog_latest_idx = evl_hdr->fw_el_latest_idx;
246 		}
247 	}
248 
249 	n = pmcs_dump_binary(pwp, pwp->fwlogp, 0, (PMCS_FWLOG_SIZE >> 2),
250 	    buf, size_left);
251 
252 	return (n);
253 }
254 
255 /*
256  * Dump Inbound and Outbound Queues.
257  */
258 static int
259 pmcs_dump_ioqs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
260 {
261 	uint8_t i = 0, k = 0;
262 	uint32_t j = 0, depth = 0;
263 	int n = 0;
264 	uint32_t *ptr = NULL;
265 
266 	n += snprintf(&buf[n], (size_left - n), "\nDump I/O queues: \n"
267 	    "-----------------\n");
268 	for (i = 0; i < PMCS_NIQ; i++) {
269 		depth = PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i)));
270 		n += snprintf(&buf[n], (size_left - n),
271 		    "IQ[%d] Details:\n-----------------\n", i);
272 		n += snprintf(&buf[n], (size_left - n),
273 		    "    depth = 0x%04x\n", depth);
274 		n += snprintf(&buf[n], (size_left - n),
275 		    "    latest ci = 0x%02x\n", pmcs_rd_iqci(pwp, i));
276 		n += snprintf(&buf[n], (size_left - n),
277 		    "    latest pi = 0x%02x\n", pmcs_rd_iqpi(pwp, i));
278 		for (j = 0; j < depth; j++) {
279 			n += snprintf(&buf[n], (size_left - n),
280 			    "IOMB[%d]:\n", j);
281 			ptr = &pwp->iqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
282 			for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
283 			    k += 8) {
284 				n += snprintf(&buf[n], (size_left - n),
285 				    "0x%08x 0x%08x 0x%08x 0x%08x "
286 				    "0x%08x 0x%08x 0x%08x 0x%08x\n",
287 				    LE_32(ptr[k]), LE_32(ptr[k+1]),
288 				    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
289 				    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
290 				    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
291 			}
292 		}
293 	}
294 	for (i = 0; i < PMCS_NOQ; i++) {
295 		depth = PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i)));
296 		n += snprintf(&buf[n], (size_left - n),
297 		    "OQ[%d] Details:\n", i);
298 		n += snprintf(&buf[n], (size_left - n),
299 		    "    depth = 0x%04x\n", depth);
300 		n += snprintf(&buf[n], (size_left - n),
301 		    "    latest ci = 0x%02x\n", pmcs_rd_oqci(pwp, i));
302 		n += snprintf(&buf[n], (size_left - n),
303 		    "    latest pi = 0x%02x\n", pmcs_rd_oqpi(pwp, i));
304 		for (j = 0; j < depth; j++) {
305 			n += snprintf(&buf[n], (size_left - n),
306 			    "IOMB[%d]:\n", j);
307 			ptr = &pwp->oqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
308 			for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
309 			    k += 8) {
310 				n += snprintf(&buf[n], (size_left - n),
311 				    "0x%08x 0x%08x 0x%08x 0x%08x "
312 				    "0x%08x 0x%08x 0x%08x 0x%08x\n",
313 				    LE_32(ptr[k]), LE_32(ptr[k+1]),
314 				    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
315 				    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
316 				    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
317 			}
318 		}
319 
320 	}
321 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
322 	    "Dump I/O queues end \n");
323 	return (n);
324 }
325 
326 /*
327  * Dump SPC Version.
328  */
329 static int
330 pmcs_dump_spc_ver(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
331 {
332 	int n = 0;
333 
334 	n += snprintf(&buf[n], (size_left - n), "\nDump SPC version: \n"
335 	    "-----------------\n");
336 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
337 	    "0x%02x\n", PMCS_FW_TYPE(pwp));
338 	n += snprintf(&buf[n], (size_left - n), "    Sub-Minor Release "
339 	    "Number = 0x%02x\n", PMCS_FW_MICRO(pwp));
340 	n += snprintf(&buf[n], (size_left - n), "    Minor Release "
341 	    "Number = 0x%02x\n", PMCS_FW_MINOR(pwp));
342 	n += snprintf(&buf[n], (size_left - n), "    Major Release "
343 	    "Number = 0x%02x\n", PMCS_FW_MAJOR(pwp));
344 	n += snprintf(&buf[n], (size_left - n), "SPC DeviceID = 0x%04x\n",
345 	    pmcs_rd_topunit(pwp, PMCS_SPC_DEVICE_ID));
346 	n += snprintf(&buf[n], (size_left - n), "SPC Device Revision = "
347 	    "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION));
348 	n += snprintf(&buf[n], (size_left - n), "SPC BootStrap Register = "
349 	    "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_SPC_BOOT_STRAP));
350 	n += snprintf(&buf[n], (size_left - n), "SPC Reset Register = 0x%08x\n",
351 	    pmcs_rd_topunit(pwp, PMCS_SPC_RESET));
352 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
353 	    "Dump SPC version end \n");
354 	return (n);
355 }
356 
357 /*
358  * Dump MPI Table.
359  */
360 static int
361 pmcs_dump_mpi_table(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
362 {
363 	int n = 0;
364 
365 	n += snprintf(&buf[n], (size_left - n), "\nDump MSGU registers: \n"
366 	    "-----------------\n");
367 	n += snprintf(&buf[n], (size_left - n), "inb_doorbell = 0x%08x\n",
368 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB));
369 	n += snprintf(&buf[n], (size_left - n), "inb_doorbell_clear = 0x%08x"
370 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR));
371 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell = 0x%08x"
372 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB));
373 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell_clear = 0x%08x"
374 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR));
375 	n += snprintf(&buf[n], (size_left - n), "scratch_pad0 = 0x%08x"
376 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0));
377 	n += snprintf(&buf[n], (size_left - n), "scratch_pad1 = 0x%08x"
378 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1));
379 	n += snprintf(&buf[n], (size_left - n), "scratch_pad2 = 0x%08x"
380 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2));
381 	n += snprintf(&buf[n], (size_left - n), "scratch_pad3 = 0x%08x"
382 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3));
383 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad0 = 0x%08x"
384 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0));
385 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad1 = 0x%08x"
386 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH1));
387 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad2 = 0x%08x"
388 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH2));
389 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad3 = 0x%08x"
390 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH3));
391 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad4 = 0x%08x"
392 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH4));
393 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad5 = 0x%08x"
394 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH5));
395 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad6 = 0x%08x"
396 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH6));
397 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad7 = 0x%08x"
398 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH7));
399 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell_mask = 0x%08x"
400 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK));
401 
402 	n += snprintf(&buf[n], (size_left - n), "MPI Configuration Table: \n"
403 	    "-----------------\n");
404 	n += snprintf(&buf[n], (size_left - n), "ASCII Signature = 0x%08x\n",
405 	    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS));
406 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
407 	    "0x%08x\n", PMCS_FW_TYPE(pwp));
408 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Variant = "
409 	    "0x%08x\n", PMCS_FW_VARIANT(pwp));
410 	n += snprintf(&buf[n], (size_left - n), "Firmware Sub-Minor Release "
411 	    "Number = 0x%08x\n", PMCS_FW_MICRO(pwp));
412 	n += snprintf(&buf[n], (size_left - n), "Firmware Minor Release "
413 	    "Number = 0x%08x\n", PMCS_FW_MINOR(pwp));
414 	n += snprintf(&buf[n], (size_left - n), "Firmware Major Release "
415 	    "Number = 0x%08x\n", PMCS_FW_MAJOR(pwp));
416 	n += snprintf(&buf[n], (size_left - n), "Maximum Outstanding I/Os "
417 	    "supported = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO));
418 	n += snprintf(&buf[n], (size_left - n), "Maximum Scatter-Gather List "
419 	    "Elements = 0x%08x\n",
420 	    PMCS_MSGL(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
421 	n += snprintf(&buf[n], (size_left - n), "Maximum number of devices "
422 	    "connected to the SPC = 0x%08x\n",
423 	    PMCS_MD(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
424 	n += snprintf(&buf[n], (size_left - n), "Maximum Number of IQs "
425 	    "supported = 0x%08x\n",
426 	    PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
427 	n += snprintf(&buf[n], (size_left - n), "Maximum Number of OQs "
428 	    "supported = 0x%08x\n",
429 	    PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
430 	n += snprintf(&buf[n], (size_left - n), "High Priority Queue supported"
431 	    " = 0x%08x\n", PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
432 	n += snprintf(&buf[n], (size_left - n), "Interrupt Coalescing supported"
433 	    " = 0x%08x\n", PMCS_ICS(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
434 	n += snprintf(&buf[n], (size_left - n), "Number of Phys = "
435 	    "0x%08x\n", PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
436 	n += snprintf(&buf[n], (size_left - n), "SAS Revision Specification = "
437 	    "0x%08x\n", PMCS_SASREV(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
438 	n += snprintf(&buf[n], (size_left - n), "General Status Table Offset = "
439 	    "0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO));
440 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Configuration "
441 	    "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO));
442 	n += snprintf(&buf[n], (size_left - n), "Outbound Queue Configuration "
443 	    "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO));
444 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Normal/High "
445 	    "Priority Processing Depth = 0x%02x 0x%02x\n",
446 	    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & IQ_NORMAL_PRI_DEPTH_MASK),
447 	    ((pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
448 	    IQ_HIPRI_PRI_DEPTH_MASK) >> IQ_HIPRI_PRI_DEPTH_SHIFT));
449 	n += snprintf(&buf[n], (size_left - n), "General Event Notification "
450 	    "Queue = 0x%02x\n", (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
451 	    GENERAL_EVENT_OQ_MASK) >> GENERAL_EVENT_OQ_SHIFT);
452 	n += snprintf(&buf[n], (size_left - n), "Device Handle Removed "
453 	    "Notification Queue = 0x%02x\n",
454 	    (uint32_t)(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
455 	    DEVICE_HANDLE_REMOVED_MASK) >> DEVICE_HANDLE_REMOVED_SHIFT);
456 	for (uint8_t i = 0; i < pwp->nphy; i++) {
457 		uint32_t woff = i / 4;
458 		uint32_t shf = (i % 4) * 8;
459 		n += snprintf(&buf[n], (size_left - n), "SAS HW Event "
460 		    "Notification Queue - PHY ID %d = 0x%02x\n", i,
461 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_EVQS + (woff << 2)) >> shf)
462 		    & 0xff);
463 	}
464 	for (uint8_t i = 0; i < pwp->nphy; i++) {
465 		uint32_t woff = i / 4;
466 		uint32_t shf = (i % 4) * 8;
467 		n += snprintf(&buf[n], (size_left - n), "SATA NCQ Error "
468 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
469 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SNCQ + (woff << 2)) >> shf)
470 		    & 0xff);
471 	}
472 	for (uint8_t i = 0; i < pwp->nphy; i++) {
473 		uint32_t woff = i / 4;
474 		uint32_t shf = (i % 4) * 8;
475 		n += snprintf(&buf[n], (size_left - n), "I_T Nexus Target "
476 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
477 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IT_NTENQ +
478 		    (woff << 2)) >> shf) & 0xff);
479 	}
480 	for (uint8_t i = 0; i < pwp->nphy; i++) {
481 		uint32_t woff = i / 4;
482 		uint32_t shf = (i % 4) * 8;
483 		n += snprintf(&buf[n], (size_left - n), "SSP Target "
484 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
485 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SSP_TENQ +
486 		    (woff << 2)) >> shf) & 0xff);
487 	}
488 	for (uint8_t i = 0; i < pwp->nphy; i++) {
489 		uint32_t woff = i / 4;
490 		uint32_t shf = (i % 4) * 8;
491 		n += snprintf(&buf[n], (size_left - n), "SMP Target "
492 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
493 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SMP_TENQ +
494 		    (woff << 2)) >> shf) & 0xff);
495 	}
496 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
497 	    "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAH));
498 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
499 	    "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAL));
500 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Size "
501 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBS));
502 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Severity "
503 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELSEV));
504 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
505 	    "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAH));
506 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
507 	    "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAL));
508 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Size "
509 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBS));
510 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Severity "
511 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELSEV));
512 	n += snprintf(&buf[n], (size_left - n), "Fatal Error Interrupt "
513 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR));
514 	n += snprintf(&buf[n], (size_left - n),
515 	    "Fatal Error Register Dump Offset "
516 	    "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU));
517 	n += snprintf(&buf[n], (size_left - n),
518 	    "Fatal Error Register Dump Length "
519 	    "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU));
520 	n += snprintf(&buf[n], (size_left - n),
521 	    "Fatal Error Register Dump Offset "
522 	    "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP));
523 	n += snprintf(&buf[n], (size_left - n),
524 	    "Fatal Error Register Dump Length "
525 	    "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP));
526 
527 	n += snprintf(&buf[n], (size_left - n), "Dump GS Table: \n"
528 	    "-----------------\n");
529 	n += snprintf(&buf[n], (size_left - n),  "GST MPI State: 0x%08x\n",
530 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE));
531 	n += snprintf(&buf[n], (size_left - n),  "Inbound Queue Freeze State 0 "
532 	    "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0));
533 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Freeze State 1 "
534 	    "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1));
535 	n += snprintf(&buf[n], (size_left - n), "MSGU Tick Count = 0x%08x \n",
536 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK));
537 	n += snprintf(&buf[n], (size_left - n), "IOP Tick Count = 0x%08x\n",
538 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK));
539 	for (uint8_t i = 0; i < pwp->nphy; i++) {
540 		n += snprintf(&buf[n], (size_left - n), " Phy %d state = "
541 		    "0x%08x\n", i, pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i)));
542 	}
543 	for (uint8_t i = 0; i < pwp->nphy; i++) {
544 		n += snprintf(&buf[n], (size_left - n), " Recoverable Error "
545 		    "Information %d = 0x%08x\n", i,
546 		    pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i)));
547 	}
548 
549 	n += snprintf(&buf[n], (size_left - n), "Dump IQCT Table\n"
550 	    "-----------------\n");
551 	for (uint8_t i = 0; i < PMCS_NIQ; i++) {
552 		n += snprintf(&buf[n], (size_left - n), "Inbound Queue "
553 		    "Configuration Table - [%d]:\n", i);
554 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
555 		    "Depth = 0x%08x\n",
556 		    PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
557 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
558 		    "Element Size and Priority = 0x%08x 0x%08x\n",
559 		    PMCS_IQESX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))),
560 		    PMCS_IQPX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
561 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
562 		    "Base Address High = 0x%08x\n",
563 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQBAHX(i)));
564 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
565 		    "Base Address Low = 0x%08x\n",
566 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQBALX(i)));
567 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
568 		    "Consumer Index Base Address High = 0x%08x\n",
569 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBAHX(i)));
570 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
571 		    "Consumer Index Base Address Low = 0x%08x\n",
572 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBALX(i)));
573 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
574 		    "Producer Index PCI BAR = 0x%08x\n",
575 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQPIBARX(i)));
576 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
577 		    "Producer Index PCI BAR offset = 0x%08x\n",
578 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i)));
579 	}
580 
581 	n += snprintf(&buf[n], (size_left - n), "Dump OQCT Table: \n"
582 	    "-----------------\n");
583 	for (uint8_t i = 0; i < PMCS_NOQ; i++) {
584 		n += snprintf(&buf[n], (size_left - n), "Outbound Queue "
585 		    "Configuration Table - [%d]:\n", i);
586 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
587 		    "Depth = 0x%08x\n",
588 		    PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
589 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
590 		    "Element Size = 0x%08x\n",
591 		    PMCS_OQESX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
592 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
593 		    "Base Address High = 0x%08x\n",
594 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQBAHX(i)));
595 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
596 		    "Base Address Low = 0x%08x\n",
597 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQBALX(i)));
598 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
599 		    "Producer Index Base Address High = 0x%08x\n",
600 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBAHX(i)));
601 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
602 		    "Producer Index Base Address Low = 0x%08x\n",
603 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBALX(i)));
604 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
605 		    "Consumer Index PCI BAR = 0x%08x\n",
606 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQCIBARX(i)));
607 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
608 		    "Consumer Index PCI BAR offset = 0x%08x\n",
609 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i)));
610 
611 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
612 		    "Interrupt Coalescing Timeout = 0x%08x\n",
613 		    PMCS_OQICT(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
614 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
615 		    "Interrupt Coalescing Count = 0x%08x\n",
616 		    PMCS_OQICC(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
617 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
618 		    "Interrupt Vector =  0x%08x\n",
619 		    PMCS_OQIV(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
620 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
621 		    "Dynamic Interrupt Coalescing Timeout = 0x%08x\n",
622 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQDICX(i)));
623 
624 	}
625 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
626 	    "Dump MPI Table end\n");
627 	return (n);
628 }
629 
630 /*ARGSUSED*/
631 int
632 pmcs_dump_binary(pmcs_hw_t *pwp, uint32_t *addr, uint32_t off,
633     uint32_t words_to_read, caddr_t buf, uint32_t size_left)
634 {
635 	uint32_t i;
636 	int n = 0;
637 	char c = ' ';
638 
639 	for (i = 0, n = 0; i < words_to_read; i++) {
640 		if ((i & 7) == 0) {
641 			n += snprintf(&buf[n], (size_left - n),
642 			    "%08x: ", (i << 2) + off);
643 		}
644 		if ((i + 1) & 7) {
645 			c = ' ';
646 		} else {
647 			c = '\n';
648 		}
649 		n += snprintf(&buf[n], (size_left - n), "%08x%c", addr[i], c);
650 	}
651 	return (n);
652 }
653 
654 /*
655  * Dump Global Shared Memory Configuration Registers
656  */
657 static int
658 pmcs_dump_gsm_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
659 {
660 	int n = 0;
661 
662 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM configuration "
663 	    "registers: \n -----------------\n");
664 	n += snprintf(&buf[n], (size_left - n), "RB6 Access Register = "
665 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, RB6_ACCESS));
666 	n += snprintf(&buf[n], (size_left - n), "CFG and RST = 0x%08x\n",
667 	    pmcs_rd_gsm_reg(pwp, GSM_CFG_AND_RESET));
668 	n += snprintf(&buf[n], (size_left - n), "RAM ECC ERR INDICATOR= "
669 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, RAM_ECC_DOUBLE_ERROR_INDICATOR));
670 	n += snprintf(&buf[n], (size_left - n), "READ ADR PARITY CHK EN = "
671 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN));
672 	n += snprintf(&buf[n], (size_left - n), "WRITE ADR PARITY CHK EN = "
673 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN));
674 	n += snprintf(&buf[n], (size_left - n), "WRITE DATA PARITY CHK EN= "
675 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN));
676 	n += snprintf(&buf[n], (size_left - n),
677 	    "READ ADR PARITY ERROR INDICATOR = 0x%08x\n",
678 	    pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_ERROR_INDICATOR));
679 	n += snprintf(&buf[n], (size_left - n),
680 	    "WRITE ADR PARITY ERROR INDICATOR = 0x%08x\n",
681 	    pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_ERROR_INDICATOR));
682 	n += snprintf(&buf[n], (size_left - n),
683 	    "WRITE DATA PARITY ERROR INDICATOR = 0x%08x\n",
684 	    pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_ERROR_INDICATOR));
685 	n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 IOP Register"
686 	    " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, NMI_EN_VPE0_IOP));
687 	n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 AAP1 Register"
688 	    " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, NMI_EN_VPE0_AAP1));
689 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
690 	    "Dump GSM configuration registers end \n");
691 	return (n);
692 }
693 
694 /*
695  * Dump PCIe Configuration Registers.
696  */
697 static int
698 pmcs_dump_pcie_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
699 {
700 	int n = 0;
701 	uint32_t i = 0;
702 
703 	n += snprintf(&buf[n], (size_left - n), "\nDump PCIe configuration "
704 	    "registers: \n -----------------\n");
705 	n += snprintf(&buf[n], (size_left - n), "VENID = 0x%04x\n",
706 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_VENID));
707 	n += snprintf(&buf[n], (size_left - n), "DEVICE_ID = 0x%04x\n",
708 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_DEVID));
709 	n += snprintf(&buf[n], (size_left - n), "CFGCMD = 0x%04x\n",
710 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_COMM));
711 	n += snprintf(&buf[n], (size_left - n), "CFGSTAT = 0x%04x\n",
712 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_STAT));
713 	n += snprintf(&buf[n], (size_left - n), "CLSCODE and REVID = 0x%08x\n",
714 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_REVID));
715 	n += snprintf(&buf[n], (size_left - n), "BIST HDRTYPE LATTIM CLSIZE = "
716 	    "0x%08x\n",
717 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_CACHE_LINESZ));
718 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-I LOWER = 0x%08x\n",
719 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE0));
720 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-I UPPER = 0x%08x\n",
721 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE1));
722 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-II LOWER = 0x%08x\n",
723 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE2));
724 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-II UPPER = 0x%08x\n",
725 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE3));
726 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-III = 0x%08x\n",
727 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE4));
728 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-IV = 0x%08x\n",
729 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE5));
730 	n += snprintf(&buf[n], (size_left - n), "SVID = 0x%08x\n",
731 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_SUBVENID));
732 	n += snprintf(&buf[n], (size_left - n), "ROMBASE = 0x%08x\n",
733 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ROM));
734 	n += snprintf(&buf[n], (size_left - n), "CAP_PTR = 0x%02x\n",
735 	    pci_config_get8(pwp->pci_acc_handle, PCI_CONF_CAP_PTR));
736 	n += snprintf(&buf[n], (size_left - n), "MAXLAT MINGNT INTPIN "
737 	    "INTLINE = 0x%08x\n",
738 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ILINE));
739 	n += snprintf(&buf[n], (size_left - n), "PMC PM_NEXT_CAP PM_CAP_ID = "
740 	    "0x%08x\n", pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMC));
741 	n += snprintf(&buf[n], (size_left - n), "PMCSR = 0x%08x\n",
742 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMCSR));
743 	n += snprintf(&buf[n], (size_left - n),
744 	    "MC MSI_NEXT_CAP MSI_CAP_ID = 0x%08x\n",
745 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSI));
746 	n += snprintf(&buf[n], (size_left - n), "MAL = 0x%08x\n",
747 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAL));
748 	n += snprintf(&buf[n], (size_left - n), "MAU = 0x%08x\n",
749 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAU));
750 	n += snprintf(&buf[n], (size_left - n), "MD = 0x%04x\n",
751 	    pci_config_get16(pwp->pci_acc_handle, PMCS_PCI_MD));
752 	n += snprintf(&buf[n], (size_left - n),
753 	    "PCIE_CAP PCIE_NEXT_CAP PCIE_CAP_ID = 0x%08x\n",
754 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE));
755 	n += snprintf(&buf[n], (size_left - n), "DEVICE_CAP = 0x%08x\n",
756 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CAP));
757 	n += snprintf(&buf[n], (size_left - n),
758 	    "DEVICE_STAT DEVICE_CTRL = 0x%08x\n",
759 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CTRL));
760 	n += snprintf(&buf[n], (size_left - n), "LINK_CAP = 0x%08x\n",
761 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CAP));
762 	n += snprintf(&buf[n], (size_left - n),
763 	    "LINK_STAT LINK_CTRL = 0x%08x\n",
764 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CTRL));
765 	n += snprintf(&buf[n], (size_left - n), "MSIX_CAP = 0x%08x\n",
766 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSIX_CAP));
767 	n += snprintf(&buf[n], (size_left - n), "TBL_OFFSET = 0x%08x\n",
768 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_TBL_OFFSET));
769 	n += snprintf(&buf[n], (size_left - n), "PBA_OFFSET = 0x%08x\n",
770 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PBA_OFFSET));
771 	n += snprintf(&buf[n], (size_left - n), "PCIE_CAP_HD = 0x%08x\n",
772 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE_CAP_HD));
773 	n += snprintf(&buf[n], (size_left - n), "UE_STAT = 0x%08x\n",
774 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_STAT));
775 	n += snprintf(&buf[n], (size_left - n), "UE_MASK = 0x%08x\n",
776 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_MASK));
777 	n += snprintf(&buf[n], (size_left - n), "UE_SEV = 0x%08x\n",
778 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_SEV));
779 	n += snprintf(&buf[n], (size_left - n), "CE_STAT = 0x%08x\n",
780 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_STAT));
781 	n += snprintf(&buf[n], (size_left - n), "CE_MASK = 0x%08x\n",
782 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_MASK));
783 	n += snprintf(&buf[n], (size_left - n), "ADV_ERR_CTRL = 0x%08x\n",
784 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_ADV_ERR_CTRL));
785 	for (i = 0; i < 4; i++) {
786 		n += snprintf(&buf[n], (size_left - n), "HD_LOG_DW%d = "
787 		    "0x%08x\n", i, pci_config_get32(pwp->pci_acc_handle,
788 		    (PMCS_PCI_HD_LOG_DW + i * 4)));
789 	}
790 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
791 	    "Dump PCIe configuration registers end \n");
792 	return (n);
793 }
794 /*
795  * Called with axil_lock held
796  */
797 static boolean_t
798 pmcs_shift_axil(pmcs_hw_t *pwp, uint32_t offset)
799 {
800 	uint32_t newaxil = offset & ~GSM_BASE_MASK;
801 
802 	ASSERT(mutex_owned(&pwp->axil_lock));
803 	ddi_put32(pwp->top_acc_handle,
804 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
805 	drv_usecwait(10);
806 
807 	if (ddi_get32(pwp->top_acc_handle,
808 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
809 		pmcs_prt(pwp, PMCS_PRT_DEBUG, "AXIL register update failed");
810 		return (B_FALSE);
811 	}
812 	return (B_TRUE);
813 }
814 
815 static uint32_t
816 pmcs_get_axil(pmcs_hw_t *pwp)
817 {
818 	uint32_t regval = 0;
819 	mutex_enter(&pwp->axil_lock);
820 	regval = ddi_get32(pwp->top_acc_handle,
821 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
822 	mutex_exit(&pwp->axil_lock);
823 	return (regval);
824 }
825 
826 static void
827 pmcs_restore_axil(pmcs_hw_t *pwp, uint32_t oldaxil)
828 {
829 	mutex_enter(&pwp->axil_lock);
830 	ddi_put32(pwp->top_acc_handle,
831 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
832 	drv_usecwait(10);
833 
834 	if (ddi_get32(pwp->top_acc_handle,
835 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
836 		pmcs_prt(pwp, PMCS_PRT_DEBUG, "AXIL register restore failed");
837 	}
838 	mutex_exit(&pwp->axil_lock);
839 }
840 
841 /*
842  * Dump GSM Memory Regions.
843  */
844 static int
845 pmcs_dump_gsm(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
846 {
847 	int n = 0;
848 	uint32_t i = 0;
849 	uint32_t oldaxil = 0;
850 	uint32_t gsm_addr = 0;
851 	uint32_t *local_buf = NULL;
852 
853 	local_buf = kmem_zalloc(GSM_SM_BLKSZ, KM_NOSLEEP);
854 	if (local_buf == NULL) {
855 		pmcs_prt(pwp, PMCS_PRT_DEBUG,
856 		    "%s: local_buf memory not allocated", __func__);
857 		return (0);
858 	}
859 
860 	oldaxil = pmcs_get_axil(pwp);
861 	mutex_enter(&pwp->axil_lock);
862 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM IO Status Table: \n"
863 	    " -----------------\n");
864 	for (i = 0; i < 4; i++) {
865 		gsm_addr = IO_STATUS_TABLE_BASE + GSM_SM_BLKSZ * i;
866 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
867 			gsm_addr &= GSM_BASE_MASK;
868 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
869 			    &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
870 			    DDI_DEV_AUTOINCR);
871 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
872 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
873 		}
874 	}
875 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
876 	    "Dump GSM IO Status Table end \n");
877 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Storage: \n"
878 	    " -----------------\n");
879 	for (i = 0; i < 2; i++) {
880 		gsm_addr = RING_BUF_STORAGE_0 + GSM_SM_BLKSZ * i;
881 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
882 			gsm_addr &= GSM_BASE_MASK;
883 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
884 			    &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
885 			    DDI_DEV_AUTOINCR);
886 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
887 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
888 		}
889 	}
890 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
891 	    "Dump Ring Buffer Storage end \n");
892 
893 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Pointers:\n"
894 	    " -----------------\n");
895 		gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_PTR_OFF;
896 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
897 			gsm_addr &= GSM_BASE_MASK;
898 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
899 			    &pwp->gsm_regs[gsm_addr >> 2],
900 			    RING_BUF_PTR_SIZE >> 2, DDI_DEV_AUTOINCR);
901 			n += pmcs_dump_binary(pwp, local_buf, 0,
902 			    RING_BUF_PTR_SIZE >> 2, &buf[n], size_left - n);
903 		}
904 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
905 	    "Dump Ring Buffer Pointers end \n");
906 
907 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Access: \n"
908 	    " -----------------\n");
909 		gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_ACC_OFF;
910 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
911 			gsm_addr &= GSM_BASE_MASK;
912 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
913 			    &pwp->gsm_regs[gsm_addr >> 2],
914 			    RING_BUF_ACC_SIZE >> 2, DDI_DEV_AUTOINCR);
915 			n += pmcs_dump_binary(pwp, local_buf, 0,
916 			    RING_BUF_ACC_SIZE >> 2, &buf[n], size_left - n);
917 		}
918 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
919 	    "Dump Ring Buffer Access end \n");
920 
921 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM SM: \n"
922 	    " -----------------\n");
923 	for (i = 0; i < 16; i++) {
924 		gsm_addr = GSM_SM_BASE + GSM_SM_BLKSZ * i;
925 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
926 			gsm_addr &= GSM_BASE_MASK;
927 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
928 			    &pwp->gsm_regs[gsm_addr >> 2],
929 			    GSM_SM_BLKSZ >> 2, DDI_DEV_AUTOINCR);
930 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
931 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
932 		}
933 	}
934 	mutex_exit(&pwp->axil_lock);
935 	pmcs_restore_axil(pwp, oldaxil);
936 
937 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
938 	    "Dump GSM SM end \n");
939 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
940 	    "\n------------ Dump GSM Memory Regions end  -------------\n");
941 	if (local_buf) {
942 		kmem_free(local_buf, GSM_SM_BLKSZ);
943 	}
944 	return (n);
945 }
946 
947 /*
948  * Trace current Inbound Message host sent to SPC.
949  */
950 void
951 pmcs_iqp_trace(pmcs_hw_t *pwp, uint32_t qnum)
952 {
953 	uint32_t k = 0, n = 0;
954 	uint32_t *ptr = NULL;
955 	char *tbuf = pwp->iqpt->curpos;
956 	uint32_t size_left = pwp->iqpt->size_left;
957 
958 	if (tbuf == NULL) {
959 		pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: trace buffer is not ready,"
960 		    " Inbound Message from host to SPC is not traced",
961 		    __func__);
962 		return;
963 	} else if (size_left < PMCS_QENTRY_SIZE * PMCS_QENTRY_SIZE) {
964 		tbuf = pwp->iqpt->curpos = pwp->iqpt->head;
965 		size_left = pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE;
966 	}
967 
968 	ptr = &pwp->iqp[qnum][pwp->shadow_iqpi[qnum] *
969 	    (PMCS_QENTRY_SIZE >> 2)];
970 	for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
971 	    k += 8) {
972 		n += snprintf(&tbuf[n], (size_left - n),
973 		    "0x%08x 0x%08x 0x%08x 0x%08x "
974 		    "0x%08x 0x%08x 0x%08x 0x%08x\n",
975 		    LE_32(ptr[k]), LE_32(ptr[k+1]),
976 		    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
977 		    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
978 		    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
979 	}
980 	pwp->iqpt->size_left -= n;
981 	if (pwp->iqpt->size_left > 0) {
982 		pwp->iqpt->curpos += n;
983 	} else {
984 		pwp->iqpt->curpos =
985 		    pwp->iqpt->head + PMCS_IQP_TRACE_BUFFER_SIZE - 1;
986 	}
987 }
988 
989 /*
990  * Dump fatal error register content from GSM.
991  */
992 int
993 pmcs_dump_feregs(pmcs_hw_t *pwp, uint32_t *addr, uint8_t nvmd,
994     caddr_t buf, uint32_t size_left)
995 {
996 	uint32_t offset = 0, length = 0;
997 	int i = 0;
998 	uint8_t *ptr = (uint8_t *)addr;
999 
1000 	if ((addr == NULL) || (buf == NULL)) {
1001 		return (0);
1002 	}
1003 	switch (nvmd) {
1004 		case PMCIN_NVMD_AAP1:
1005 			offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU);
1006 			length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU);
1007 			break;
1008 		case PMCIN_NVMD_IOP:
1009 			offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP);
1010 			length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP);
1011 			break;
1012 		default:
1013 			pmcs_prt(pwp, PMCS_PRT_DEBUG, "UNKNOWN NVMD DEVICE"
1014 			    "%s():%d", __func__, __LINE__);
1015 			return (0);
1016 	}
1017 
1018 	while ((i < length) && (ptr[i + offset] != 0xff) &&
1019 	    (ptr[i + offset] != '\0')) {
1020 		i += snprintf(&buf[i], (size_left - i),
1021 		    "%c", ptr[i + offset]);
1022 	}
1023 	return (i);
1024 }
1025