xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_fwlog.c (revision 861a91627796c35220e75654dac61e5707536dcd)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  *
21  *
22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file contains firmware log routines.
28  */
29 
30 #include <sys/scsi/adapters/pmcs/pmcs.h>
31 #include <sys/scsi/adapters/pmcs/pmcs_fwlog.h>
32 
33 static int pmcs_dump_ioqs(pmcs_hw_t *, caddr_t, uint32_t);
34 static int pmcs_dump_spc_ver(pmcs_hw_t *, caddr_t, uint32_t);
35 static int pmcs_dump_mpi_table(pmcs_hw_t *, caddr_t, uint32_t);
36 static int pmcs_dump_gsm_conf(pmcs_hw_t *, caddr_t, uint32_t);
37 static int pmcs_dump_pcie_conf(pmcs_hw_t *, caddr_t, uint32_t);
38 static uint32_t pmcs_get_axil(pmcs_hw_t *);
39 static boolean_t pmcs_shift_axil(pmcs_hw_t *, uint32_t);
40 static void pmcs_restore_axil(pmcs_hw_t *, uint32_t);
41 static int pmcs_dump_gsm(pmcs_hw_t *, caddr_t, uint32_t);
42 static int pmcs_dump_gsm_addiregs(pmcs_hw_t *, caddr_t, uint32_t);
43 static int pmcs_dump_hsst_sregs(pmcs_hw_t *, caddr_t, uint32_t);
44 static int pmcs_dump_sspa_sregs(pmcs_hw_t *, caddr_t, uint32_t);
45 static int pmcs_dump_fwlog(pmcs_hw_t *, caddr_t, uint32_t);
46 static void pmcs_write_fwlog(pmcs_hw_t *, pmcs_fw_event_hdr_t *);
47 
48 /*
49  * Dump internal registers. Used after a firmware crash.
50  * Here dump various registers for firmware forensics,
51  * including MPI, GSM configuration, firmware log, IO Queues etc.
52  */
53 void
54 pmcs_register_dump_int(pmcs_hw_t *pwp)
55 {
56 	int n = 0;
57 	uint32_t size_left = 0;
58 	uint8_t slice = 0;
59 	caddr_t buf = NULL;
60 
61 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
62 	    "pmcs%d: Internal register dump", ddi_get_instance(pwp->dip));
63 	ASSERT(mutex_owned(&pwp->lock));
64 
65 	if (pwp->regdumpp == NULL) {
66 		pwp->regdumpp =
67 		    kmem_zalloc(PMCS_REG_DUMP_SIZE, KM_NOSLEEP);
68 		if (pwp->regdumpp == NULL) {
69 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
70 			    "%s: register dump memory not allocated", __func__);
71 			return;
72 		}
73 	}
74 	buf = pwp->regdumpp;
75 	size_left = PMCS_REG_DUMP_SIZE - 1;
76 
77 	n = pmcs_dump_spc_ver(pwp, buf, size_left);
78 	ASSERT(size_left >= n);
79 	buf += n; size_left -= n;
80 	n = pmcs_dump_gsm_conf(pwp, buf, size_left);
81 	ASSERT(size_left >= n);
82 	buf += n; size_left -= n;
83 	n = pmcs_dump_pcie_conf(pwp, buf, size_left);
84 	ASSERT(size_left >= n);
85 	buf += n; size_left -= n;
86 	n = pmcs_dump_mpi_table(pwp, buf, size_left);
87 	ASSERT(size_left >= n);
88 	buf += n; size_left -= n;
89 	n = pmcs_dump_ioqs(pwp, buf, size_left);
90 	ASSERT(size_left >= n);
91 	buf += n; size_left -= n;
92 
93 	if (pwp->state == STATE_DEAD) {
94 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
95 		    "%s: HBA dead, skipping AAP1/IOP registers and event logs",
96 		    __func__);
97 		goto skip_logs;
98 	}
99 
100 	mutex_exit(&pwp->lock);
101 	slice = (PMCS_REGISTER_DUMP_FLASH_SIZE / PMCS_FLASH_CHUNK_SIZE);
102 	n = snprintf(buf, size_left, "\nDump AAP1 register: \n"
103 	    "-----------------\n");
104 	ASSERT(size_left >= n);
105 	buf += n; size_left -= n;
106 	for (uint8_t j = 0; j < slice; j++) {
107 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
108 		    PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
109 		    buf, size_left);
110 		if (n == PMCS_FLASH_CHUNK_SIZE) {
111 			ASSERT(size_left >= n);
112 			buf += n; size_left -= n;
113 		} else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
114 			ASSERT(size_left >= n);
115 			buf += n; size_left -= n;
116 			break;
117 		} else if (n == 0) {
118 			n = snprintf(buf, size_left, "AAP1: Content of "
119 			    "register dump on flash is NULL\n");
120 			ASSERT(size_left >= n);
121 			buf += n; size_left -= n;
122 			break;
123 		} else {
124 			n = snprintf(buf, size_left,
125 			    "AAP1: Unable to obtain internal register dump\n");
126 			ASSERT(size_left >= n);
127 			buf += n; size_left -= n;
128 			break;
129 		}
130 
131 	}
132 
133 	n = snprintf(buf, size_left, "\nDump IOP register: \n"
134 	    "-----------------\n");
135 	ASSERT(size_left >= n);
136 	buf += n; size_left -= n;
137 	for (uint8_t j = 0; j < slice; j++) {
138 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
139 		    PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
140 		    buf, size_left);
141 		if (n == PMCS_FLASH_CHUNK_SIZE) {
142 			ASSERT(size_left >= n);
143 			buf += n; size_left -= n;
144 		} else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
145 			ASSERT(size_left >= n);
146 			buf += n; size_left -= n;
147 			break;
148 		} else if (n == 0) {
149 			n = snprintf(buf, size_left,
150 			    "IOP: Content of internal register dump is NULL\n");
151 			ASSERT(size_left >= n);
152 			buf += n; size_left -= n;
153 			break;
154 		} else {
155 			n = snprintf(buf, size_left,
156 			    "IOP: Unable to obtain internal register dump\n");
157 			ASSERT(size_left >= n);
158 			buf += n; size_left -= n;
159 			break;
160 		}
161 
162 	}
163 
164 	n = snprintf(buf, size_left, "\nDump AAP1 event log: \n"
165 	    "-----------------\n");
166 	ASSERT(size_left >= n);
167 	buf += n; size_left -= n;
168 	for (uint8_t j = 0; j < slice; j++) {
169 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
170 		    PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
171 		    buf, size_left);
172 		if (n > 0) {
173 			ASSERT(size_left >= n);
174 			buf += n; size_left -= n;
175 		} else {
176 			n = snprintf(buf, size_left,
177 			    "AAP1: Unable to obtain event log on flash\n");
178 			ASSERT(size_left >= n);
179 			buf += n; size_left -= n;
180 			break;
181 		}
182 	}
183 
184 	n = snprintf(buf, size_left, "\nDump IOP event log: \n"
185 	    "-----------------\n");
186 	ASSERT(size_left >= n);
187 	buf += n; size_left -= n;
188 	for (uint8_t j = 0; j < slice; j++) {
189 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
190 		    PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
191 		    buf, size_left);
192 		if (n > 0) {
193 			ASSERT(size_left >= n);
194 			buf += n; size_left -= n;
195 		} else {
196 			n = snprintf(buf, size_left,
197 			    "IOP: Unable to obtain event log dump\n");
198 			ASSERT(size_left >= n);
199 			buf += n; size_left -= n;
200 			break;
201 		}
202 	}
203 	mutex_enter(&pwp->lock);
204 
205 skip_logs:
206 	n = pmcs_dump_gsm_addiregs(pwp, buf, size_left);
207 	ASSERT(size_left >= n);
208 	buf += n; size_left -= n;
209 
210 	n = pmcs_dump_hsst_sregs(pwp, buf, size_left);
211 	ASSERT(size_left >= n);
212 	buf += n; size_left -= n;
213 
214 	n = pmcs_dump_sspa_sregs(pwp, buf, size_left);
215 	ASSERT(size_left >= n);
216 	buf += n; size_left -= n;
217 	n = snprintf(buf, size_left, "\nDump firmware log: \n"
218 	    "-----------------\n");
219 	ASSERT(size_left >= n);
220 	buf += n; size_left -= n;
221 
222 	n = pmcs_dump_fwlog(pwp, buf, size_left);
223 	ASSERT(size_left >= n);
224 	buf += n; size_left -= n;
225 
226 	n = pmcs_dump_gsm(pwp, buf, size_left);
227 	ASSERT(size_left >= n);
228 	buf += n; size_left -= n;
229 
230 	n = snprintf(buf, size_left, "-----------------\n"
231 	    "\n------------ Dump internal registers end  -------------\n");
232 	ASSERT(size_left >= n);
233 	buf += n; size_left -= n;
234 }
235 
236 static int
237 pmcs_dump_fwlog(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
238 {
239 	pmcs_fw_event_hdr_t *evl_hdr;
240 	int n = 0, retries = 0;
241 	uint32_t evlog_latest_idx;
242 	boolean_t log_is_current = B_FALSE;
243 
244 	if (pwp->fwlogp == NULL) {
245 		n = snprintf(buf, size_left, "\nFirmware logging "
246 		    "not enabled\n");
247 		return (n);
248 	}
249 
250 	/*
251 	 * First, check to make sure all entries have been DMAed to the
252 	 * log buffer.
253 	 *
254 	 * We'll wait the required 50ms, but if the latest entry keeps
255 	 * changing, we'll only retry twice
256 	 */
257 	evl_hdr = (pmcs_fw_event_hdr_t *)pwp->fwlogp;
258 	evlog_latest_idx = evl_hdr->fw_el_latest_idx;
259 
260 	while ((log_is_current == B_FALSE) && (retries < 3)) {
261 		drv_usecwait(50 * 1000);
262 		if (evl_hdr->fw_el_latest_idx == evlog_latest_idx) {
263 			log_is_current = B_TRUE;
264 		} else {
265 			++retries;
266 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
267 			    "%s: event log is still being updated... waiting",
268 			    __func__);
269 			evlog_latest_idx = evl_hdr->fw_el_latest_idx;
270 		}
271 	}
272 
273 	n = pmcs_dump_binary(pwp, pwp->fwlogp, 0, (PMCS_FWLOG_SIZE >> 2),
274 	    buf, size_left);
275 
276 	return (n);
277 }
278 
279 /*
280  * Dump Inbound and Outbound Queues.
281  */
282 static int
283 pmcs_dump_ioqs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
284 {
285 	uint8_t i = 0, k = 0;
286 	uint32_t j = 0, depth = 0;
287 	int n = 0;
288 	uint32_t *ptr = NULL;
289 
290 	n += snprintf(&buf[n], (size_left - n), "\nDump I/O queues: \n"
291 	    "-----------------\n");
292 	for (i = 0; i < PMCS_NIQ; i++) {
293 		depth = PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i)));
294 		n += snprintf(&buf[n], (size_left - n),
295 		    "IQ[%d] Details:\n-----------------\n", i);
296 		n += snprintf(&buf[n], (size_left - n),
297 		    "    depth = 0x%04x\n", depth);
298 		n += snprintf(&buf[n], (size_left - n),
299 		    "    latest ci = 0x%02x\n", pmcs_rd_iqci(pwp, i));
300 		n += snprintf(&buf[n], (size_left - n),
301 		    "    latest pi = 0x%02x\n", pmcs_rd_iqpi(pwp, i));
302 		for (j = 0; j < depth; j++) {
303 			n += snprintf(&buf[n], (size_left - n),
304 			    "IOMB[%d]:\n", j);
305 			ptr = &pwp->iqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
306 			for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
307 			    k += 8) {
308 				n += snprintf(&buf[n], (size_left - n),
309 				    "0x%08x 0x%08x 0x%08x 0x%08x "
310 				    "0x%08x 0x%08x 0x%08x 0x%08x\n",
311 				    LE_32(ptr[k]), LE_32(ptr[k+1]),
312 				    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
313 				    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
314 				    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
315 			}
316 		}
317 	}
318 	for (i = 0; i < PMCS_NOQ; i++) {
319 		depth = PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i)));
320 		n += snprintf(&buf[n], (size_left - n),
321 		    "OQ[%d] Details:\n", i);
322 		n += snprintf(&buf[n], (size_left - n),
323 		    "    depth = 0x%04x\n", depth);
324 		n += snprintf(&buf[n], (size_left - n),
325 		    "    latest ci = 0x%02x\n", pmcs_rd_oqci(pwp, i));
326 		n += snprintf(&buf[n], (size_left - n),
327 		    "    latest pi = 0x%02x\n", pmcs_rd_oqpi(pwp, i));
328 		for (j = 0; j < depth; j++) {
329 			n += snprintf(&buf[n], (size_left - n),
330 			    "IOMB[%d]:\n", j);
331 			ptr = &pwp->oqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
332 			for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
333 			    k += 8) {
334 				n += snprintf(&buf[n], (size_left - n),
335 				    "0x%08x 0x%08x 0x%08x 0x%08x "
336 				    "0x%08x 0x%08x 0x%08x 0x%08x\n",
337 				    LE_32(ptr[k]), LE_32(ptr[k+1]),
338 				    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
339 				    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
340 				    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
341 			}
342 		}
343 
344 	}
345 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
346 	    "Dump I/O queues end \n");
347 	return (n);
348 }
349 
350 /*
351  * Dump SPC Version.
352  */
353 static int
354 pmcs_dump_spc_ver(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
355 {
356 	int n = 0;
357 
358 	n += snprintf(&buf[n], (size_left - n), "\nDump SPC version: \n"
359 	    "-----------------\n");
360 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
361 	    "0x%02x\n", PMCS_FW_TYPE(pwp));
362 	n += snprintf(&buf[n], (size_left - n), "    Sub-Minor Release "
363 	    "Number = 0x%02x\n", PMCS_FW_MICRO(pwp));
364 	n += snprintf(&buf[n], (size_left - n), "    Minor Release "
365 	    "Number = 0x%02x\n", PMCS_FW_MINOR(pwp));
366 	n += snprintf(&buf[n], (size_left - n), "    Major Release "
367 	    "Number = 0x%02x\n", PMCS_FW_MAJOR(pwp));
368 	n += snprintf(&buf[n], (size_left - n), "SPC DeviceID = 0x%04x\n",
369 	    pmcs_rd_topunit(pwp, PMCS_SPC_DEVICE_ID));
370 	n += snprintf(&buf[n], (size_left - n), "SPC Device Revision = "
371 	    "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION));
372 	n += snprintf(&buf[n], (size_left - n), "SPC BootStrap Register = "
373 	    "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_SPC_BOOT_STRAP));
374 	n += snprintf(&buf[n], (size_left - n), "SPC Reset Register = 0x%08x\n",
375 	    pmcs_rd_topunit(pwp, PMCS_SPC_RESET));
376 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
377 	    "Dump SPC version end \n");
378 	return (n);
379 }
380 
381 /*
382  * Dump MPI Table.
383  */
384 static int
385 pmcs_dump_mpi_table(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
386 {
387 	int n = 0;
388 
389 	n += snprintf(&buf[n], (size_left - n), "\nDump MSGU registers: \n"
390 	    "-----------------\n");
391 	n += snprintf(&buf[n], (size_left - n), "inb_doorbell = 0x%08x\n",
392 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB));
393 	n += snprintf(&buf[n], (size_left - n), "inb_doorbell_clear = 0x%08x"
394 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR));
395 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell = 0x%08x"
396 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB));
397 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell_clear = 0x%08x"
398 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR));
399 	n += snprintf(&buf[n], (size_left - n), "scratch_pad0 = 0x%08x"
400 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0));
401 	n += snprintf(&buf[n], (size_left - n), "scratch_pad1 = 0x%08x"
402 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1));
403 	n += snprintf(&buf[n], (size_left - n), "scratch_pad2 = 0x%08x"
404 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2));
405 	n += snprintf(&buf[n], (size_left - n), "scratch_pad3 = 0x%08x"
406 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3));
407 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad0 = 0x%08x"
408 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0));
409 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad1 = 0x%08x"
410 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH1));
411 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad2 = 0x%08x"
412 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH2));
413 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad3 = 0x%08x"
414 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH3));
415 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad4 = 0x%08x"
416 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH4));
417 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad5 = 0x%08x"
418 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH5));
419 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad6 = 0x%08x"
420 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH6));
421 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad7 = 0x%08x"
422 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH7));
423 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell_mask = 0x%08x"
424 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK));
425 
426 	n += snprintf(&buf[n], (size_left - n), "MPI Configuration Table: \n"
427 	    "-----------------\n");
428 	n += snprintf(&buf[n], (size_left - n), "ASCII Signature = 0x%08x\n",
429 	    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS));
430 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
431 	    "0x%08x\n", PMCS_FW_TYPE(pwp));
432 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Variant = "
433 	    "0x%08x\n", PMCS_FW_VARIANT(pwp));
434 	n += snprintf(&buf[n], (size_left - n), "Firmware Sub-Minor Release "
435 	    "Number = 0x%08x\n", PMCS_FW_MICRO(pwp));
436 	n += snprintf(&buf[n], (size_left - n), "Firmware Minor Release "
437 	    "Number = 0x%08x\n", PMCS_FW_MINOR(pwp));
438 	n += snprintf(&buf[n], (size_left - n), "Firmware Major Release "
439 	    "Number = 0x%08x\n", PMCS_FW_MAJOR(pwp));
440 	n += snprintf(&buf[n], (size_left - n), "Maximum Outstanding I/Os "
441 	    "supported = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO));
442 	n += snprintf(&buf[n], (size_left - n), "Maximum Scatter-Gather List "
443 	    "Elements = 0x%08x\n",
444 	    PMCS_MSGL(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
445 	n += snprintf(&buf[n], (size_left - n), "Maximum number of devices "
446 	    "connected to the SPC = 0x%08x\n",
447 	    PMCS_MD(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
448 	n += snprintf(&buf[n], (size_left - n), "Maximum Number of IQs "
449 	    "supported = 0x%08x\n",
450 	    PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
451 	n += snprintf(&buf[n], (size_left - n), "Maximum Number of OQs "
452 	    "supported = 0x%08x\n",
453 	    PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
454 	n += snprintf(&buf[n], (size_left - n), "High Priority Queue supported"
455 	    " = 0x%08x\n", PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
456 	n += snprintf(&buf[n], (size_left - n), "Interrupt Coalescing supported"
457 	    " = 0x%08x\n", PMCS_ICS(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
458 	n += snprintf(&buf[n], (size_left - n), "Number of Phys = "
459 	    "0x%08x\n", PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
460 	n += snprintf(&buf[n], (size_left - n), "SAS Revision Specification = "
461 	    "0x%08x\n", PMCS_SASREV(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
462 	n += snprintf(&buf[n], (size_left - n), "General Status Table Offset = "
463 	    "0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO));
464 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Configuration "
465 	    "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO));
466 	n += snprintf(&buf[n], (size_left - n), "Outbound Queue Configuration "
467 	    "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO));
468 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Normal/High "
469 	    "Priority Processing Depth = 0x%02x 0x%02x\n",
470 	    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & IQ_NORMAL_PRI_DEPTH_MASK),
471 	    ((pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
472 	    IQ_HIPRI_PRI_DEPTH_MASK) >> IQ_HIPRI_PRI_DEPTH_SHIFT));
473 	n += snprintf(&buf[n], (size_left - n), "General Event Notification "
474 	    "Queue = 0x%02x\n", (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
475 	    GENERAL_EVENT_OQ_MASK) >> GENERAL_EVENT_OQ_SHIFT);
476 	n += snprintf(&buf[n], (size_left - n), "Device Handle Removed "
477 	    "Notification Queue = 0x%02x\n",
478 	    (uint32_t)(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
479 	    DEVICE_HANDLE_REMOVED_MASK) >> DEVICE_HANDLE_REMOVED_SHIFT);
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), "SAS HW Event "
484 		    "Notification Queue - PHY ID %d = 0x%02x\n", i,
485 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_EVQS + (woff << 2)) >> shf)
486 		    & 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), "SATA NCQ Error "
492 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
493 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SNCQ + (woff << 2)) >> shf)
494 		    & 0xff);
495 	}
496 	for (uint8_t i = 0; i < pwp->nphy; i++) {
497 		uint32_t woff = i / 4;
498 		uint32_t shf = (i % 4) * 8;
499 		n += snprintf(&buf[n], (size_left - n), "I_T Nexus Target "
500 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
501 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IT_NTENQ +
502 		    (woff << 2)) >> shf) & 0xff);
503 	}
504 	for (uint8_t i = 0; i < pwp->nphy; i++) {
505 		uint32_t woff = i / 4;
506 		uint32_t shf = (i % 4) * 8;
507 		n += snprintf(&buf[n], (size_left - n), "SSP Target "
508 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
509 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SSP_TENQ +
510 		    (woff << 2)) >> shf) & 0xff);
511 	}
512 
513 	n += snprintf(&buf[n], (size_left - n), "I/O Abort Delay = 0x%04x\n",
514 	    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IOABTDLY) & 0xffff);
515 	n += snprintf(&buf[n], (size_left - n),
516 	    "Customization Setting = 0x%08x\n",
517 	    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_CUSTSET));
518 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
519 	    "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAH));
520 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
521 	    "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAL));
522 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Size "
523 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBS));
524 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Severity "
525 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELSEV));
526 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
527 	    "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAH));
528 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
529 	    "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAL));
530 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Size "
531 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBS));
532 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Severity "
533 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELSEV));
534 	n += snprintf(&buf[n], (size_left - n), "Fatal Error Interrupt "
535 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR));
536 	n += snprintf(&buf[n], (size_left - n),
537 	    "Fatal Error Register Dump Offset "
538 	    "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU));
539 	n += snprintf(&buf[n], (size_left - n),
540 	    "Fatal Error Register Dump Length "
541 	    "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU));
542 	n += snprintf(&buf[n], (size_left - n),
543 	    "Fatal Error Register Dump Offset "
544 	    "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP));
545 	n += snprintf(&buf[n], (size_left - n),
546 	    "Fatal Error Register Dump Length "
547 	    "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP));
548 
549 	n += snprintf(&buf[n], (size_left - n), "Dump GS Table: \n"
550 	    "-----------------\n");
551 	n += snprintf(&buf[n], (size_left - n),  "GST MPI State: 0x%08x\n",
552 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE));
553 	n += snprintf(&buf[n], (size_left - n),  "Inbound Queue Freeze State 0 "
554 	    "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0));
555 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Freeze State 1 "
556 	    "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1));
557 	n += snprintf(&buf[n], (size_left - n), "MSGU Tick Count = 0x%08x \n",
558 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK));
559 	n += snprintf(&buf[n], (size_left - n), "IOP Tick Count = 0x%08x\n",
560 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK));
561 	for (uint8_t i = 0; i < pwp->nphy; i++) {
562 		n += snprintf(&buf[n], (size_left - n), " Phy %d state = "
563 		    "0x%08x\n", i, pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i)));
564 	}
565 	for (uint8_t i = 0; i < pwp->nphy; i++) {
566 		n += snprintf(&buf[n], (size_left - n), " Recoverable Error "
567 		    "Information %d = 0x%08x\n", i,
568 		    pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i)));
569 	}
570 
571 	n += snprintf(&buf[n], (size_left - n), "Dump IQCT Table\n"
572 	    "-----------------\n");
573 	for (uint8_t i = 0; i < PMCS_NIQ; i++) {
574 		n += snprintf(&buf[n], (size_left - n), "Inbound Queue "
575 		    "Configuration Table - [%d]:\n", i);
576 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
577 		    "Depth = 0x%08x\n",
578 		    PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
579 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
580 		    "Element Size and Priority = 0x%08x 0x%08x\n",
581 		    PMCS_IQESX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))),
582 		    PMCS_IQPX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
583 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
584 		    "Base Address High = 0x%08x\n",
585 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQBAHX(i)));
586 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
587 		    "Base Address Low = 0x%08x\n",
588 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQBALX(i)));
589 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
590 		    "Consumer Index Base Address High = 0x%08x\n",
591 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBAHX(i)));
592 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
593 		    "Consumer Index Base Address Low = 0x%08x\n",
594 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBALX(i)));
595 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
596 		    "Producer Index PCI BAR = 0x%08x\n",
597 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQPIBARX(i)));
598 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
599 		    "Producer Index PCI BAR offset = 0x%08x\n",
600 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i)));
601 	}
602 
603 	n += snprintf(&buf[n], (size_left - n), "Dump OQCT Table: \n"
604 	    "-----------------\n");
605 	for (uint8_t i = 0; i < PMCS_NOQ; i++) {
606 		n += snprintf(&buf[n], (size_left - n), "Outbound Queue "
607 		    "Configuration Table - [%d]:\n", i);
608 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
609 		    "Depth = 0x%08x\n",
610 		    PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
611 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
612 		    "Element Size = 0x%08x\n",
613 		    PMCS_OQESX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
614 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
615 		    "Base Address High = 0x%08x\n",
616 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQBAHX(i)));
617 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
618 		    "Base Address Low = 0x%08x\n",
619 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQBALX(i)));
620 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
621 		    "Producer Index Base Address High = 0x%08x\n",
622 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBAHX(i)));
623 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
624 		    "Producer Index Base Address Low = 0x%08x\n",
625 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBALX(i)));
626 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
627 		    "Consumer Index PCI BAR = 0x%08x\n",
628 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQCIBARX(i)));
629 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
630 		    "Consumer Index PCI BAR offset = 0x%08x\n",
631 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i)));
632 
633 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
634 		    "Interrupt Coalescing Timeout = 0x%08x\n",
635 		    PMCS_OQICT(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
636 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
637 		    "Interrupt Coalescing Count = 0x%08x\n",
638 		    PMCS_OQICC(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
639 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
640 		    "Interrupt Vector =  0x%08x\n",
641 		    PMCS_OQIV(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
642 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
643 		    "Dynamic Interrupt Coalescing Timeout = 0x%08x\n",
644 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQDICX(i)));
645 
646 	}
647 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
648 	    "Dump MPI Table end\n");
649 	return (n);
650 }
651 
652 /*ARGSUSED*/
653 int
654 pmcs_dump_binary(pmcs_hw_t *pwp, uint32_t *addr, uint32_t off,
655     uint32_t words_to_read, caddr_t buf, uint32_t size_left)
656 {
657 	uint32_t i;
658 	int n = 0;
659 	char c = ' ';
660 
661 	for (i = 0, n = 0; i < words_to_read; i++) {
662 		if ((i & 7) == 0) {
663 			n += snprintf(&buf[n], (size_left - n),
664 			    "%08x: ", (i << 2) + off);
665 		}
666 		if ((i + 1) & 7) {
667 			c = ' ';
668 		} else {
669 			c = '\n';
670 		}
671 		n += snprintf(&buf[n], (size_left - n), "%08x%c", addr[i], c);
672 	}
673 	return (n);
674 }
675 
676 /*
677  * Dump Global Shared Memory Configuration Registers
678  */
679 static int
680 pmcs_dump_gsm_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
681 {
682 	int n = 0;
683 
684 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM configuration "
685 	    "registers: \n -----------------\n");
686 	n += snprintf(&buf[n], (size_left - n), "RB6 Access Register = "
687 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, RB6_ACCESS));
688 	n += snprintf(&buf[n], (size_left - n), "CFG and RST = 0x%08x\n",
689 	    pmcs_rd_gsm_reg(pwp, 0, GSM_CFG_AND_RESET));
690 	n += snprintf(&buf[n], (size_left - n), "RAM ECC ERR INDICATOR= "
691 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0,
692 	    RAM_ECC_DOUBLE_ERROR_INDICATOR));
693 	n += snprintf(&buf[n], (size_left - n), "READ ADR PARITY CHK EN = "
694 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_CHK_EN));
695 	n += snprintf(&buf[n], (size_left - n), "WRITE ADR PARITY CHK EN = "
696 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_CHK_EN));
697 	n += snprintf(&buf[n], (size_left - n), "WRITE DATA PARITY CHK EN= "
698 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_CHK_EN));
699 	n += snprintf(&buf[n], (size_left - n),
700 	    "READ ADR PARITY ERROR INDICATOR = 0x%08x\n",
701 	    pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_ERROR_INDICATOR));
702 	n += snprintf(&buf[n], (size_left - n),
703 	    "WRITE ADR PARITY ERROR INDICATOR = 0x%08x\n",
704 	    pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_ERROR_INDICATOR));
705 	n += snprintf(&buf[n], (size_left - n),
706 	    "WRITE DATA PARITY ERROR INDICATOR = 0x%08x\n",
707 	    pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_ERROR_INDICATOR));
708 	n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 IOP Register"
709 	    " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, NMI_EN_VPE0_IOP));
710 	n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 AAP1 Register"
711 	    " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, NMI_EN_VPE0_AAP1));
712 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
713 	    "Dump GSM configuration registers end \n");
714 	return (n);
715 }
716 
717 /*
718  * Dump PCIe Configuration Registers.
719  */
720 static int
721 pmcs_dump_pcie_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
722 {
723 	int n = 0;
724 	uint32_t i = 0;
725 
726 	n += snprintf(&buf[n], (size_left - n), "\nDump PCIe configuration "
727 	    "registers: \n -----------------\n");
728 	n += snprintf(&buf[n], (size_left - n), "VENID = 0x%04x\n",
729 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_VENID));
730 	n += snprintf(&buf[n], (size_left - n), "DEVICE_ID = 0x%04x\n",
731 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_DEVID));
732 	n += snprintf(&buf[n], (size_left - n), "CFGCMD = 0x%04x\n",
733 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_COMM));
734 	n += snprintf(&buf[n], (size_left - n), "CFGSTAT = 0x%04x\n",
735 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_STAT));
736 	n += snprintf(&buf[n], (size_left - n), "CLSCODE and REVID = 0x%08x\n",
737 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_REVID));
738 	n += snprintf(&buf[n], (size_left - n), "BIST HDRTYPE LATTIM CLSIZE = "
739 	    "0x%08x\n",
740 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_CACHE_LINESZ));
741 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-I LOWER = 0x%08x\n",
742 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE0));
743 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-I UPPER = 0x%08x\n",
744 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE1));
745 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-II LOWER = 0x%08x\n",
746 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE2));
747 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-II UPPER = 0x%08x\n",
748 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE3));
749 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-III = 0x%08x\n",
750 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE4));
751 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-IV = 0x%08x\n",
752 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE5));
753 	n += snprintf(&buf[n], (size_left - n), "SVID = 0x%08x\n",
754 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_SUBVENID));
755 	n += snprintf(&buf[n], (size_left - n), "ROMBASE = 0x%08x\n",
756 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ROM));
757 	n += snprintf(&buf[n], (size_left - n), "CAP_PTR = 0x%02x\n",
758 	    pci_config_get8(pwp->pci_acc_handle, PCI_CONF_CAP_PTR));
759 	n += snprintf(&buf[n], (size_left - n), "MAXLAT MINGNT INTPIN "
760 	    "INTLINE = 0x%08x\n",
761 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ILINE));
762 	n += snprintf(&buf[n], (size_left - n), "PMC PM_NEXT_CAP PM_CAP_ID = "
763 	    "0x%08x\n", pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMC));
764 	n += snprintf(&buf[n], (size_left - n), "PMCSR = 0x%08x\n",
765 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMCSR));
766 	n += snprintf(&buf[n], (size_left - n),
767 	    "MC MSI_NEXT_CAP MSI_CAP_ID = 0x%08x\n",
768 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSI));
769 	n += snprintf(&buf[n], (size_left - n), "MAL = 0x%08x\n",
770 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAL));
771 	n += snprintf(&buf[n], (size_left - n), "MAU = 0x%08x\n",
772 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAU));
773 	n += snprintf(&buf[n], (size_left - n), "MD = 0x%04x\n",
774 	    pci_config_get16(pwp->pci_acc_handle, PMCS_PCI_MD));
775 	n += snprintf(&buf[n], (size_left - n),
776 	    "PCIE_CAP PCIE_NEXT_CAP PCIE_CAP_ID = 0x%08x\n",
777 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE));
778 	n += snprintf(&buf[n], (size_left - n), "DEVICE_CAP = 0x%08x\n",
779 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CAP));
780 	n += snprintf(&buf[n], (size_left - n),
781 	    "DEVICE_STAT DEVICE_CTRL = 0x%08x\n",
782 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CTRL));
783 	n += snprintf(&buf[n], (size_left - n), "LINK_CAP = 0x%08x\n",
784 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CAP));
785 	n += snprintf(&buf[n], (size_left - n),
786 	    "LINK_STAT LINK_CTRL = 0x%08x\n",
787 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CTRL));
788 	n += snprintf(&buf[n], (size_left - n), "MSIX_CAP = 0x%08x\n",
789 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSIX_CAP));
790 	n += snprintf(&buf[n], (size_left - n), "TBL_OFFSET = 0x%08x\n",
791 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_TBL_OFFSET));
792 	n += snprintf(&buf[n], (size_left - n), "PBA_OFFSET = 0x%08x\n",
793 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PBA_OFFSET));
794 	n += snprintf(&buf[n], (size_left - n), "PCIE_CAP_HD = 0x%08x\n",
795 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE_CAP_HD));
796 	n += snprintf(&buf[n], (size_left - n), "UE_STAT = 0x%08x\n",
797 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_STAT));
798 	n += snprintf(&buf[n], (size_left - n), "UE_MASK = 0x%08x\n",
799 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_MASK));
800 	n += snprintf(&buf[n], (size_left - n), "UE_SEV = 0x%08x\n",
801 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_SEV));
802 	n += snprintf(&buf[n], (size_left - n), "CE_STAT = 0x%08x\n",
803 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_STAT));
804 	n += snprintf(&buf[n], (size_left - n), "CE_MASK = 0x%08x\n",
805 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_MASK));
806 	n += snprintf(&buf[n], (size_left - n), "ADV_ERR_CTRL = 0x%08x\n",
807 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_ADV_ERR_CTRL));
808 	for (i = 0; i < 4; i++) {
809 		n += snprintf(&buf[n], (size_left - n), "HD_LOG_DW%d = "
810 		    "0x%08x\n", i, pci_config_get32(pwp->pci_acc_handle,
811 		    (PMCS_PCI_HD_LOG_DW + i * 4)));
812 	}
813 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
814 	    "Dump PCIe configuration registers end \n");
815 	return (n);
816 }
817 /*
818  * Called with axil_lock held
819  */
820 static boolean_t
821 pmcs_shift_axil(pmcs_hw_t *pwp, uint32_t offset)
822 {
823 	uint32_t newaxil = offset & ~GSM_BASE_MASK;
824 
825 	ASSERT(mutex_owned(&pwp->axil_lock));
826 	ddi_put32(pwp->top_acc_handle,
827 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
828 	drv_usecwait(10);
829 
830 	if (ddi_get32(pwp->top_acc_handle,
831 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
832 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
833 		    "AXIL register update failed");
834 		return (B_FALSE);
835 	}
836 	return (B_TRUE);
837 }
838 
839 static uint32_t
840 pmcs_get_axil(pmcs_hw_t *pwp)
841 {
842 	uint32_t regval = 0;
843 	mutex_enter(&pwp->axil_lock);
844 	regval = ddi_get32(pwp->top_acc_handle,
845 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
846 	mutex_exit(&pwp->axil_lock);
847 	return (regval);
848 }
849 
850 static void
851 pmcs_restore_axil(pmcs_hw_t *pwp, uint32_t oldaxil)
852 {
853 	mutex_enter(&pwp->axil_lock);
854 	ddi_put32(pwp->top_acc_handle,
855 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
856 	drv_usecwait(10);
857 
858 	if (ddi_get32(pwp->top_acc_handle,
859 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
860 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
861 		    "AXIL register restore failed");
862 	}
863 	mutex_exit(&pwp->axil_lock);
864 }
865 
866 /*
867  * Dump Additional GSM Registers.
868  */
869 static int
870 pmcs_dump_gsm_addiregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
871 {
872 	uint32_t i = 0;
873 	int n = 0, j = 0, nums = 0;
874 	uint32_t gsm_addr = 0, addr = 0;
875 
876 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM Sparse Registers:"
877 	    "\n-----------------\n");
878 	for (i = 0; i < sizeof (gsm_spregs) / sizeof (pmcs_sparse_regs_t);
879 	    i++) {
880 		gsm_addr =
881 		    gsm_spregs[i].shift_addr + gsm_spregs[i].offset_start;
882 		nums = gsm_spregs[i].offset_end - gsm_spregs[i].offset_start;
883 		if (gsm_spregs[i].flag & PMCS_SPREGS_BLOCK_START) {
884 			n += snprintf(&buf[n], (size_left - n), "\n%s - 0x%08X"
885 			    "[MEMBASE-III SHIFT = 0x%08X]\nOffset:\n",
886 			    gsm_spregs[i].desc ? gsm_spregs[i].desc : "NULL",
887 			    gsm_spregs[i].base_addr, gsm_spregs[i].shift_addr);
888 		}
889 
890 		if (nums == 0) {
891 			n += snprintf(&buf[n], (size_left - n),
892 			    "[%04X]: %08X\n", gsm_spregs[i].offset_start,
893 			    pmcs_rd_gsm_reg(pwp, 0, gsm_addr));
894 		} else if (nums > 0) {
895 			n += snprintf(&buf[n], (size_left - n),
896 			    "\n[%04X] - [%04X]: \n", gsm_spregs[i].offset_start,
897 			    gsm_spregs[i].offset_end);
898 
899 			j = 0;
900 			while (nums > 0) {
901 				addr = gsm_addr + j * 4;
902 				n += snprintf(&buf[n], (size_left - n),
903 				    "[%04X]: %08X\n", addr & GSM_BASE_MASK,
904 				    pmcs_rd_gsm_reg(pwp, 0, addr));
905 				j++;
906 				nums -= 4;
907 			}
908 		}
909 
910 	}
911 
912 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
913 	    "------------ Dump GSM Sparse Registers end ------------\n");
914 	return (n);
915 
916 }
917 
918 /*
919  * Dump GSM Memory Regions.
920  */
921 static int
922 pmcs_dump_gsm(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
923 {
924 	int n = 0;
925 	uint32_t i = 0;
926 	uint32_t oldaxil = 0;
927 	uint32_t gsm_addr = 0;
928 	uint32_t *local_buf = NULL;
929 
930 	local_buf = kmem_zalloc(GSM_SM_BLKSZ, KM_NOSLEEP);
931 	if (local_buf == NULL) {
932 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
933 		    "%s: local_buf memory not allocated", __func__);
934 		return (0);
935 	}
936 
937 	oldaxil = pmcs_get_axil(pwp);
938 	mutex_enter(&pwp->axil_lock);
939 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM IO Status Table: \n"
940 	    " -----------------\n");
941 	for (i = 0; i < 4; i++) {
942 		gsm_addr = IO_STATUS_TABLE_BASE + GSM_SM_BLKSZ * i;
943 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
944 			gsm_addr &= GSM_BASE_MASK;
945 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
946 			    &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
947 			    DDI_DEV_AUTOINCR);
948 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
949 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
950 		}
951 	}
952 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
953 	    "Dump GSM IO Status Table end \n");
954 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Storage: \n"
955 	    " -----------------\n");
956 	for (i = 0; i < 2; i++) {
957 		gsm_addr = RING_BUF_STORAGE_0 + GSM_SM_BLKSZ * i;
958 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
959 			gsm_addr &= GSM_BASE_MASK;
960 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
961 			    &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
962 			    DDI_DEV_AUTOINCR);
963 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
964 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
965 		}
966 	}
967 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
968 	    "Dump Ring Buffer Storage end \n");
969 
970 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Pointers:\n"
971 	    " -----------------\n");
972 		gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_PTR_OFF;
973 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
974 			gsm_addr &= GSM_BASE_MASK;
975 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
976 			    &pwp->gsm_regs[gsm_addr >> 2],
977 			    RING_BUF_PTR_SIZE >> 2, DDI_DEV_AUTOINCR);
978 			n += pmcs_dump_binary(pwp, local_buf, 0,
979 			    RING_BUF_PTR_SIZE >> 2, &buf[n], size_left - n);
980 		}
981 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
982 	    "Dump Ring Buffer Pointers end \n");
983 
984 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Access: \n"
985 	    " -----------------\n");
986 		gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_ACC_OFF;
987 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
988 			gsm_addr &= GSM_BASE_MASK;
989 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
990 			    &pwp->gsm_regs[gsm_addr >> 2],
991 			    RING_BUF_ACC_SIZE >> 2, DDI_DEV_AUTOINCR);
992 			n += pmcs_dump_binary(pwp, local_buf, 0,
993 			    RING_BUF_ACC_SIZE >> 2, &buf[n], size_left - n);
994 		}
995 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
996 	    "Dump Ring Buffer Access end \n");
997 
998 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM SM: \n"
999 	    " -----------------\n");
1000 	for (i = 0; i < 16; i++) {
1001 		gsm_addr = GSM_SM_BASE + GSM_SM_BLKSZ * i;
1002 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
1003 			gsm_addr &= GSM_BASE_MASK;
1004 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
1005 			    &pwp->gsm_regs[gsm_addr >> 2],
1006 			    GSM_SM_BLKSZ >> 2, DDI_DEV_AUTOINCR);
1007 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
1008 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
1009 		}
1010 	}
1011 	mutex_exit(&pwp->axil_lock);
1012 	pmcs_restore_axil(pwp, oldaxil);
1013 
1014 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
1015 	    "Dump GSM SM end \n");
1016 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
1017 	    "\n------------ Dump GSM Memory Regions end  -------------\n");
1018 	if (local_buf) {
1019 		kmem_free(local_buf, GSM_SM_BLKSZ);
1020 	}
1021 	return (n);
1022 }
1023 
1024 /*
1025  * Trace current Inbound Message host sent to SPC.
1026  */
1027 void
1028 pmcs_iqp_trace(pmcs_hw_t *pwp, uint32_t qnum)
1029 {
1030 	uint32_t k = 0;
1031 	int n = 0;
1032 	uint32_t *ptr = NULL;
1033 	char *tbuf = pwp->iqpt->curpos;
1034 	uint32_t size_left = pwp->iqpt->size_left;
1035 
1036 	if (tbuf == NULL) {
1037 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1038 		    "%s: trace buffer is not ready,"
1039 		    " Inbound Message from host to SPC is not traced",
1040 		    __func__);
1041 		return;
1042 	} else if (size_left < PMCS_QENTRY_SIZE * PMCS_QENTRY_SIZE) {
1043 		tbuf = pwp->iqpt->curpos = pwp->iqpt->head;
1044 		size_left = pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE;
1045 	}
1046 
1047 	ptr = &pwp->iqp[qnum][pwp->shadow_iqpi[qnum] *
1048 	    (PMCS_QENTRY_SIZE >> 2)];
1049 	for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
1050 	    k += 8) {
1051 		n += snprintf(&tbuf[n], (size_left - n),
1052 		    "0x%08x 0x%08x 0x%08x 0x%08x "
1053 		    "0x%08x 0x%08x 0x%08x 0x%08x\n",
1054 		    LE_32(ptr[k]), LE_32(ptr[k+1]),
1055 		    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
1056 		    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
1057 		    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
1058 	}
1059 	pwp->iqpt->size_left -= n;
1060 	if (pwp->iqpt->size_left > 0) {
1061 		pwp->iqpt->curpos += n;
1062 	} else {
1063 		pwp->iqpt->curpos =
1064 		    pwp->iqpt->head + PMCS_IQP_TRACE_BUFFER_SIZE - 1;
1065 	}
1066 }
1067 
1068 /*
1069  * Capture HSST State Registers.
1070  */
1071 static int
1072 pmcs_dump_hsst_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
1073 {
1074 	uint32_t i = 0, j = 0, addr = 0;
1075 	int n = 0;
1076 
1077 	n += snprintf(&buf[n], (size_left - n), "\nHSST State Capture : \n"
1078 	    "-----------------\n");
1079 	n += snprintf(&buf[n], (size_left - n), "%s \t %s \n",
1080 	    hsst_state[8].desc ? hsst_state[8].desc : "NULL",
1081 	    hsst_state[16].desc ? hsst_state[16].desc : "NULL");
1082 
1083 	for (i = 0; i < 8; i++) {
1084 		addr = hsst_state[i].offset_start +
1085 		    hsst_state[i].shift_addr;
1086 		n += snprintf(&buf[n], (size_left - n), "Phy[%1d]\n", i);
1087 		for (j = 0; j < 6; j++) {
1088 			pmcs_wr_gsm_reg(pwp, addr, j);
1089 			pmcs_wr_gsm_reg(pwp, addr, (0x0100 + j));
1090 			addr = hsst_state[i+8].offset_start +
1091 			    hsst_state[i+8].shift_addr;
1092 			n += snprintf(&buf[n], (size_left - n),
1093 			    "[%08X]: %08X\t", addr, pmcs_rd_gsm_reg(pwp, 0,
1094 			    addr));
1095 			addr = hsst_state[i+16].offset_start +
1096 			    hsst_state[i+16].shift_addr;
1097 			n += snprintf(&buf[n], (size_left - n),
1098 			    "[%08X]: %08X\n", addr, pmcs_rd_gsm_reg(pwp, 0,
1099 			    addr));
1100 		}
1101 
1102 	}
1103 	return (n);
1104 
1105 }
1106 
1107 /*
1108  * Capture SSPA State Registers.
1109  */
1110 static int
1111 pmcs_dump_sspa_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
1112 {
1113 	uint32_t i = 0, rv = 0, addr = 0;
1114 	int n = 0;
1115 
1116 	n += snprintf(&buf[n], (size_left - n), "\nSSPA State Capture : \n"
1117 	    "-----------------\n");
1118 	for (i = 0; i < 8; i++) {
1119 		if (sspa_state[i].flag & PMCS_SPREGS_BLOCK_START) {
1120 			n += snprintf(&buf[n], (size_left - n), "%s \n",
1121 			    sspa_state[i].desc ? sspa_state[i].desc : "NULL");
1122 		}
1123 		addr = sspa_state[i].offset_start + sspa_state[i].shift_addr;
1124 		rv = pmcs_rd_gsm_reg(pwp, 0, addr);
1125 		rv |= PMCS_SSPA_CONTROL_REGISTER_BIT27;
1126 		pmcs_wr_gsm_reg(pwp, addr, rv);
1127 		n += snprintf(&buf[n], (size_left - n), "[%08X]: %08X \n",
1128 		    addr, pmcs_rd_gsm_reg(pwp, 0, addr));
1129 
1130 	}
1131 	return (n);
1132 }
1133 
1134 /*
1135  * Dump fatal error register content from GSM.
1136  */
1137 int
1138 pmcs_dump_feregs(pmcs_hw_t *pwp, uint32_t *addr, uint8_t nvmd,
1139     caddr_t buf, uint32_t size_left)
1140 {
1141 	uint32_t offset = 0, length = 0;
1142 	int i = 0;
1143 	uint8_t *ptr = (uint8_t *)addr;
1144 
1145 	if ((addr == NULL) || (buf == NULL)) {
1146 		return (0);
1147 	}
1148 	switch (nvmd) {
1149 		case PMCIN_NVMD_AAP1:
1150 			offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU);
1151 			length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU);
1152 			break;
1153 		case PMCIN_NVMD_IOP:
1154 			offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP);
1155 			length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP);
1156 			break;
1157 		default:
1158 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1159 			    "UNKNOWN NVMD DEVICE %s():%d", __func__, __LINE__);
1160 			return (0);
1161 	}
1162 
1163 	while ((i < length) && (ptr[i + offset] != 0xff) &&
1164 	    (ptr[i + offset] != '\0')) {
1165 		i += snprintf(&buf[i], (size_left - i),
1166 		    "%c", ptr[i + offset]);
1167 	}
1168 	return (i);
1169 }
1170 
1171 /*
1172  * Write out either the AAP1 or IOP event log
1173  */
1174 static void
1175 pmcs_write_fwlog(pmcs_hw_t *pwp, pmcs_fw_event_hdr_t *fwlogp)
1176 {
1177 	struct vnode *vnp;
1178 	caddr_t fwlogfile, bufp;
1179 	rlim64_t rlimit;
1180 	ssize_t resid;
1181 	offset_t offset = 0;
1182 	int error;
1183 	uint32_t data_len;
1184 
1185 	if (fwlogp == pwp->fwlogp_aap1) {
1186 		fwlogfile = pwp->fwlogfile_aap1;
1187 	} else {
1188 		fwlogfile = pwp->fwlogfile_iop;
1189 	}
1190 
1191 	if ((error = vn_open(fwlogfile, UIO_SYSSPACE, FCREAT|FWRITE, 0644,
1192 	    &vnp, CRCREAT, 0)) != 0) {
1193 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1194 		    "%s: Could not create '%s', error %d", __func__,
1195 		    fwlogfile, error);
1196 		return;
1197 	}
1198 
1199 	bufp = (caddr_t)fwlogp;
1200 	data_len = PMCS_FWLOG_SIZE / 2;
1201 	rlimit = data_len + 1;
1202 	for (;;) {
1203 		error = vn_rdwr(UIO_WRITE, vnp, bufp, data_len, offset,
1204 		    UIO_SYSSPACE, FSYNC, rlimit, CRED(), &resid);
1205 		if (error) {
1206 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1207 			    "%s: could not write %s, error %d", __func__,
1208 			    fwlogfile, error);
1209 			break;
1210 		}
1211 		if (resid == data_len) {
1212 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1213 			    "%s: Out of space in %s, error %d", __func__,
1214 			    fwlogfile, error);
1215 			error = ENOSPC;
1216 			break;
1217 		}
1218 		if (resid == 0)
1219 			break;
1220 		offset += (data_len - resid);
1221 		data_len = (ssize_t)resid;
1222 	}
1223 
1224 	if (error = VOP_CLOSE(vnp, FWRITE, 1, (offset_t)0, kcred, NULL)) {
1225 		if (!error) {
1226 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1227 			    "%s: Error on close %s, error %d", __func__,
1228 			    fwlogfile, error);
1229 		}
1230 	}
1231 
1232 	VN_RELE(vnp);
1233 }
1234 
1235 /*
1236  * Check the in-memory event log.  If it's filled up to or beyond the
1237  * threshold, write it out to the configured filename.
1238  */
1239 void
1240 pmcs_gather_fwlog(pmcs_hw_t *pwp)
1241 {
1242 	uint32_t num_entries_aap1, num_entries_iop, fname_suffix;
1243 
1244 	ASSERT(!mutex_owned(&pwp->lock));
1245 
1246 	/*
1247 	 * Get our copies of the latest indices
1248 	 */
1249 	pwp->fwlog_latest_idx_aap1 = pwp->fwlogp_aap1->fw_el_latest_idx;
1250 	pwp->fwlog_latest_idx_iop = pwp->fwlogp_iop->fw_el_latest_idx;
1251 
1252 	/*
1253 	 * We need entries in the log before we can know how big they are
1254 	 */
1255 	if ((pwp->fwlog_max_entries_aap1 == 0) &&
1256 	    (pwp->fwlogp_aap1->fw_el_latest_idx != 0)) {
1257 		pwp->fwlog_max_entries_aap1 =
1258 		    (PMCS_FWLOG_SIZE / 2) / pwp->fwlogp_aap1->fw_el_entry_size;
1259 		pwp->fwlog_threshold_aap1 =
1260 		    (pwp->fwlog_max_entries_aap1 * PMCS_FWLOG_THRESH) / 100;
1261 	}
1262 
1263 	if ((pwp->fwlog_max_entries_iop == 0) &&
1264 	    (pwp->fwlogp_iop->fw_el_latest_idx != 0)) {
1265 		pwp->fwlog_max_entries_iop =
1266 		    (PMCS_FWLOG_SIZE / 2) / pwp->fwlogp_iop->fw_el_entry_size;
1267 		pwp->fwlog_threshold_iop =
1268 		    (pwp->fwlog_max_entries_iop * PMCS_FWLOG_THRESH) / 100;
1269 	}
1270 
1271 	/*
1272 	 * Check if we've reached the threshold in the AAP1 log.  We do this
1273 	 * by comparing the latest index with our copy of the oldest index
1274 	 * (not the chip's).
1275 	 */
1276 	if (pwp->fwlog_latest_idx_aap1 >= pwp->fwlog_oldest_idx_aap1) {
1277 		/* Log has not wrapped */
1278 		num_entries_aap1 =
1279 		    pwp->fwlog_latest_idx_aap1 - pwp->fwlog_oldest_idx_aap1;
1280 	} else {
1281 		/* Log has wrapped */
1282 		num_entries_aap1 = pwp->fwlog_max_entries_aap1 -
1283 		    (pwp->fwlog_oldest_idx_aap1 - pwp->fwlog_latest_idx_aap1);
1284 	}
1285 
1286 	/*
1287 	 * Now check the IOP log
1288 	 */
1289 	if (pwp->fwlog_latest_idx_iop >= pwp->fwlog_oldest_idx_iop) {
1290 		/* Log has not wrapped */
1291 		num_entries_iop = pwp->fwlog_latest_idx_iop -
1292 		    pwp->fwlog_oldest_idx_iop;
1293 	} else {
1294 		/* Log has wrapped */
1295 		num_entries_iop = pwp->fwlog_max_entries_iop -
1296 		    (pwp->fwlog_oldest_idx_iop - pwp->fwlog_latest_idx_iop);
1297 	}
1298 
1299 	if ((num_entries_aap1 < pwp->fwlog_threshold_aap1) &&
1300 	    (num_entries_iop < pwp->fwlog_threshold_iop)) {
1301 		return;
1302 	}
1303 
1304 	/*
1305 	 * We also can't write the event log out if it's too early in boot
1306 	 * (i.e. the root fs isn't mounted yet).
1307 	 */
1308 	if (!modrootloaded) {
1309 		return;
1310 	}
1311 
1312 	/*
1313 	 * Write out the necessary log file(s), update the "oldest" pointers
1314 	 * and the suffix to the written filenames.
1315 	 */
1316 	if (num_entries_aap1 >= pwp->fwlog_threshold_aap1) {
1317 		pmcs_write_fwlog(pwp, pwp->fwlogp_aap1);
1318 		pwp->fwlog_oldest_idx_aap1 = pwp->fwlog_latest_idx_aap1;
1319 
1320 		fname_suffix = strlen(pwp->fwlogfile_aap1) - 1;
1321 		if (pwp->fwlogfile_aap1[fname_suffix] == '4') {
1322 			pwp->fwlogfile_aap1[fname_suffix] = '0';
1323 		} else {
1324 			++pwp->fwlogfile_aap1[fname_suffix];
1325 		}
1326 	}
1327 
1328 	if (num_entries_iop >= pwp->fwlog_threshold_iop) {
1329 		pmcs_write_fwlog(pwp, pwp->fwlogp_iop);
1330 		pwp->fwlog_oldest_idx_iop = pwp->fwlog_latest_idx_iop;
1331 
1332 		fname_suffix = strlen(pwp->fwlogfile_iop) - 1;
1333 		if (pwp->fwlogfile_iop[fname_suffix] == '4') {
1334 			pwp->fwlogfile_iop[fname_suffix] = '0';
1335 		} else {
1336 			++pwp->fwlogfile_iop[fname_suffix];
1337 		}
1338 	}
1339 }
1340