xref: /onnv-gate/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_fwlog.c (revision 12462:6a2cdc3dccf5)
110696SDavid.Hollister@Sun.COM /*
210696SDavid.Hollister@Sun.COM  * CDDL HEADER START
310696SDavid.Hollister@Sun.COM  *
410696SDavid.Hollister@Sun.COM  * The contents of this file are subject to the terms of the
510696SDavid.Hollister@Sun.COM  * Common Development and Distribution License (the "License").
610696SDavid.Hollister@Sun.COM  * You may not use this file except in compliance with the License.
710696SDavid.Hollister@Sun.COM  *
810696SDavid.Hollister@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910696SDavid.Hollister@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010696SDavid.Hollister@Sun.COM  * See the License for the specific language governing permissions
1110696SDavid.Hollister@Sun.COM  * and limitations under the License.
1210696SDavid.Hollister@Sun.COM  *
1310696SDavid.Hollister@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410696SDavid.Hollister@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510696SDavid.Hollister@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610696SDavid.Hollister@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710696SDavid.Hollister@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810696SDavid.Hollister@Sun.COM  *
1910696SDavid.Hollister@Sun.COM  * CDDL HEADER END
20*12462Sjesse.butler@oracle.com  */
21*12462Sjesse.butler@oracle.com /*
22*12462Sjesse.butler@oracle.com  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2310696SDavid.Hollister@Sun.COM  */
2410696SDavid.Hollister@Sun.COM 
2510696SDavid.Hollister@Sun.COM /*
2610696SDavid.Hollister@Sun.COM  * This file contains firmware log routines.
2710696SDavid.Hollister@Sun.COM  */
2810696SDavid.Hollister@Sun.COM 
2910696SDavid.Hollister@Sun.COM #include <sys/scsi/adapters/pmcs/pmcs.h>
3011425SBing.Hu@Sun.COM #include <sys/scsi/adapters/pmcs/pmcs_fwlog.h>
3110696SDavid.Hollister@Sun.COM 
3210696SDavid.Hollister@Sun.COM static int pmcs_dump_ioqs(pmcs_hw_t *, caddr_t, uint32_t);
3310696SDavid.Hollister@Sun.COM static int pmcs_dump_spc_ver(pmcs_hw_t *, caddr_t, uint32_t);
3410696SDavid.Hollister@Sun.COM static int pmcs_dump_mpi_table(pmcs_hw_t *, caddr_t, uint32_t);
3510696SDavid.Hollister@Sun.COM static int pmcs_dump_gsm_conf(pmcs_hw_t *, caddr_t, uint32_t);
3610696SDavid.Hollister@Sun.COM static int pmcs_dump_pcie_conf(pmcs_hw_t *, caddr_t, uint32_t);
3710696SDavid.Hollister@Sun.COM static uint32_t pmcs_get_axil(pmcs_hw_t *);
3810696SDavid.Hollister@Sun.COM static boolean_t pmcs_shift_axil(pmcs_hw_t *, uint32_t);
3910696SDavid.Hollister@Sun.COM static void pmcs_restore_axil(pmcs_hw_t *, uint32_t);
4010696SDavid.Hollister@Sun.COM static int pmcs_dump_gsm(pmcs_hw_t *, caddr_t, uint32_t);
4111425SBing.Hu@Sun.COM static int pmcs_dump_gsm_addiregs(pmcs_hw_t *, caddr_t, uint32_t);
4211425SBing.Hu@Sun.COM static int pmcs_dump_hsst_sregs(pmcs_hw_t *, caddr_t, uint32_t);
4311425SBing.Hu@Sun.COM static int pmcs_dump_sspa_sregs(pmcs_hw_t *, caddr_t, uint32_t);
4410696SDavid.Hollister@Sun.COM static int pmcs_dump_fwlog(pmcs_hw_t *, caddr_t, uint32_t);
4511694SDavid.Hollister@Sun.COM static void pmcs_write_fwlog(pmcs_hw_t *, pmcs_fw_event_hdr_t *);
4610696SDavid.Hollister@Sun.COM 
4710696SDavid.Hollister@Sun.COM /*
4810696SDavid.Hollister@Sun.COM  * Dump internal registers. Used after a firmware crash.
4910696SDavid.Hollister@Sun.COM  * Here dump various registers for firmware forensics,
5010696SDavid.Hollister@Sun.COM  * including MPI, GSM configuration, firmware log, IO Queues etc.
5110696SDavid.Hollister@Sun.COM  */
5210696SDavid.Hollister@Sun.COM void
pmcs_register_dump_int(pmcs_hw_t * pwp)5310696SDavid.Hollister@Sun.COM pmcs_register_dump_int(pmcs_hw_t *pwp)
5410696SDavid.Hollister@Sun.COM {
5510696SDavid.Hollister@Sun.COM 	int n = 0;
5610696SDavid.Hollister@Sun.COM 	uint32_t size_left = 0;
57*12462Sjesse.butler@oracle.com 	uint32_t scratch = 0;
5810696SDavid.Hollister@Sun.COM 	uint8_t slice = 0;
5910696SDavid.Hollister@Sun.COM 	caddr_t buf = NULL;
6010696SDavid.Hollister@Sun.COM 
61*12462Sjesse.butler@oracle.com 	ASSERT(mutex_owned(&pwp->lock));
62*12462Sjesse.butler@oracle.com 
6311048SDavid.Hollister@Sun.COM 	pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
6411048SDavid.Hollister@Sun.COM 	    "pmcs%d: Internal register dump", ddi_get_instance(pwp->dip));
6510696SDavid.Hollister@Sun.COM 
6610696SDavid.Hollister@Sun.COM 	if (pwp->regdumpp == NULL) {
6710696SDavid.Hollister@Sun.COM 		pwp->regdumpp =
6810696SDavid.Hollister@Sun.COM 		    kmem_zalloc(PMCS_REG_DUMP_SIZE, KM_NOSLEEP);
6910696SDavid.Hollister@Sun.COM 		if (pwp->regdumpp == NULL) {
7011048SDavid.Hollister@Sun.COM 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
7111048SDavid.Hollister@Sun.COM 			    "%s: register dump memory not allocated", __func__);
7210696SDavid.Hollister@Sun.COM 			return;
7310696SDavid.Hollister@Sun.COM 		}
7410696SDavid.Hollister@Sun.COM 	}
7510696SDavid.Hollister@Sun.COM 	buf = pwp->regdumpp;
7610696SDavid.Hollister@Sun.COM 	size_left = PMCS_REG_DUMP_SIZE - 1;
7710696SDavid.Hollister@Sun.COM 
7810696SDavid.Hollister@Sun.COM 	n = pmcs_dump_spc_ver(pwp, buf, size_left);
7910696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
8010696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
8110696SDavid.Hollister@Sun.COM 	n = pmcs_dump_gsm_conf(pwp, buf, size_left);
8210696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
8310696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
8410696SDavid.Hollister@Sun.COM 	n = pmcs_dump_pcie_conf(pwp, buf, size_left);
8510696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
8610696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
8710696SDavid.Hollister@Sun.COM 	n = pmcs_dump_mpi_table(pwp, buf, size_left);
8810696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
8910696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
9010696SDavid.Hollister@Sun.COM 	n = pmcs_dump_ioqs(pwp, buf, size_left);
9110696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
9210696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
9311847SDavid.Hollister@Sun.COM 
9411847SDavid.Hollister@Sun.COM 	if (pwp->state == STATE_DEAD) {
9511847SDavid.Hollister@Sun.COM 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
9611847SDavid.Hollister@Sun.COM 		    "%s: HBA dead, skipping AAP1/IOP registers and event logs",
9711847SDavid.Hollister@Sun.COM 		    __func__);
9811847SDavid.Hollister@Sun.COM 		goto skip_logs;
9911847SDavid.Hollister@Sun.COM 	}
10011847SDavid.Hollister@Sun.COM 
101*12462Sjesse.butler@oracle.com 	scratch = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
102*12462Sjesse.butler@oracle.com 	if ((scratch & PMCS_MSGU_AAP_STATE_MASK) == PMCS_MSGU_AAP_STATE_ERROR) {
103*12462Sjesse.butler@oracle.com 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
104*12462Sjesse.butler@oracle.com 		    "%s: MSGU in error state, skipping AAP1/IOP registers and "
105*12462Sjesse.butler@oracle.com 		    "event logs", __func__);
106*12462Sjesse.butler@oracle.com 		goto skip_logs;
107*12462Sjesse.butler@oracle.com 	}
108*12462Sjesse.butler@oracle.com 
10910696SDavid.Hollister@Sun.COM 	mutex_exit(&pwp->lock);
11010696SDavid.Hollister@Sun.COM 	slice = (PMCS_REGISTER_DUMP_FLASH_SIZE / PMCS_FLASH_CHUNK_SIZE);
11110696SDavid.Hollister@Sun.COM 	n = snprintf(buf, size_left, "\nDump AAP1 register: \n"
11210696SDavid.Hollister@Sun.COM 	    "-----------------\n");
11310696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
11410696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
11510696SDavid.Hollister@Sun.COM 	for (uint8_t j = 0; j < slice; j++) {
11610696SDavid.Hollister@Sun.COM 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
11710696SDavid.Hollister@Sun.COM 		    PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
11810696SDavid.Hollister@Sun.COM 		    buf, size_left);
11910696SDavid.Hollister@Sun.COM 		if (n == PMCS_FLASH_CHUNK_SIZE) {
12010696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
12110696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
12210696SDavid.Hollister@Sun.COM 		} else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
12310696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
12410696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
12510696SDavid.Hollister@Sun.COM 			break;
12610696SDavid.Hollister@Sun.COM 		} else if (n == 0) {
12710696SDavid.Hollister@Sun.COM 			n = snprintf(buf, size_left, "AAP1: Content of "
12810696SDavid.Hollister@Sun.COM 			    "register dump on flash is NULL\n");
12910696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
13010696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
13110696SDavid.Hollister@Sun.COM 			break;
13210696SDavid.Hollister@Sun.COM 		} else {
13310696SDavid.Hollister@Sun.COM 			n = snprintf(buf, size_left,
13410696SDavid.Hollister@Sun.COM 			    "AAP1: Unable to obtain internal register dump\n");
13510696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
13610696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
13710696SDavid.Hollister@Sun.COM 			break;
13810696SDavid.Hollister@Sun.COM 		}
13910696SDavid.Hollister@Sun.COM 
14010696SDavid.Hollister@Sun.COM 	}
14110696SDavid.Hollister@Sun.COM 
14210696SDavid.Hollister@Sun.COM 	n = snprintf(buf, size_left, "\nDump IOP register: \n"
14310696SDavid.Hollister@Sun.COM 	    "-----------------\n");
14410696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
14510696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
14610696SDavid.Hollister@Sun.COM 	for (uint8_t j = 0; j < slice; j++) {
14710696SDavid.Hollister@Sun.COM 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_REG_DUMP,
14810696SDavid.Hollister@Sun.COM 		    PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
14910696SDavid.Hollister@Sun.COM 		    buf, size_left);
15010696SDavid.Hollister@Sun.COM 		if (n == PMCS_FLASH_CHUNK_SIZE) {
15110696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
15210696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
15310696SDavid.Hollister@Sun.COM 		} else if ((n < PMCS_FLASH_CHUNK_SIZE) && (n > 0)) {
15410696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
15510696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
15610696SDavid.Hollister@Sun.COM 			break;
15710696SDavid.Hollister@Sun.COM 		} else if (n == 0) {
15810696SDavid.Hollister@Sun.COM 			n = snprintf(buf, size_left,
15910696SDavid.Hollister@Sun.COM 			    "IOP: Content of internal register dump is NULL\n");
16010696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
16110696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
16210696SDavid.Hollister@Sun.COM 			break;
16310696SDavid.Hollister@Sun.COM 		} else {
16410696SDavid.Hollister@Sun.COM 			n = snprintf(buf, size_left,
16510696SDavid.Hollister@Sun.COM 			    "IOP: Unable to obtain internal register dump\n");
16610696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
16710696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
16810696SDavid.Hollister@Sun.COM 			break;
16910696SDavid.Hollister@Sun.COM 		}
17010696SDavid.Hollister@Sun.COM 
17110696SDavid.Hollister@Sun.COM 	}
17210696SDavid.Hollister@Sun.COM 
17310696SDavid.Hollister@Sun.COM 	n = snprintf(buf, size_left, "\nDump AAP1 event log: \n"
17410696SDavid.Hollister@Sun.COM 	    "-----------------\n");
17510696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
17610696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
17710696SDavid.Hollister@Sun.COM 	for (uint8_t j = 0; j < slice; j++) {
17810696SDavid.Hollister@Sun.COM 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
17910696SDavid.Hollister@Sun.COM 		    PMCIN_NVMD_AAP1, (j * PMCS_FLASH_CHUNK_SIZE),
18010696SDavid.Hollister@Sun.COM 		    buf, size_left);
18110696SDavid.Hollister@Sun.COM 		if (n > 0) {
18210696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
18310696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
18410696SDavid.Hollister@Sun.COM 		} else {
18510696SDavid.Hollister@Sun.COM 			n = snprintf(buf, size_left,
18610696SDavid.Hollister@Sun.COM 			    "AAP1: Unable to obtain event log on flash\n");
18710696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
18810696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
18910696SDavid.Hollister@Sun.COM 			break;
19010696SDavid.Hollister@Sun.COM 		}
19110696SDavid.Hollister@Sun.COM 	}
19210696SDavid.Hollister@Sun.COM 
19310696SDavid.Hollister@Sun.COM 	n = snprintf(buf, size_left, "\nDump IOP event log: \n"
19410696SDavid.Hollister@Sun.COM 	    "-----------------\n");
19510696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
19610696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
19710696SDavid.Hollister@Sun.COM 	for (uint8_t j = 0; j < slice; j++) {
19810696SDavid.Hollister@Sun.COM 		n = pmcs_get_nvmd(pwp, PMCS_NVMD_EVENT_LOG,
19910696SDavid.Hollister@Sun.COM 		    PMCIN_NVMD_IOP, (j * PMCS_FLASH_CHUNK_SIZE),
20010696SDavid.Hollister@Sun.COM 		    buf, size_left);
20110696SDavid.Hollister@Sun.COM 		if (n > 0) {
20210696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
20310696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
20410696SDavid.Hollister@Sun.COM 		} else {
20510696SDavid.Hollister@Sun.COM 			n = snprintf(buf, size_left,
20610696SDavid.Hollister@Sun.COM 			    "IOP: Unable to obtain event log dump\n");
20710696SDavid.Hollister@Sun.COM 			ASSERT(size_left >= n);
20810696SDavid.Hollister@Sun.COM 			buf += n; size_left -= n;
20910696SDavid.Hollister@Sun.COM 			break;
21010696SDavid.Hollister@Sun.COM 		}
21110696SDavid.Hollister@Sun.COM 	}
21210696SDavid.Hollister@Sun.COM 	mutex_enter(&pwp->lock);
21310696SDavid.Hollister@Sun.COM 
21411847SDavid.Hollister@Sun.COM skip_logs:
21511425SBing.Hu@Sun.COM 	n = pmcs_dump_gsm_addiregs(pwp, buf, size_left);
21611425SBing.Hu@Sun.COM 	ASSERT(size_left >= n);
21711425SBing.Hu@Sun.COM 	buf += n; size_left -= n;
21811425SBing.Hu@Sun.COM 
21911425SBing.Hu@Sun.COM 	n = pmcs_dump_hsst_sregs(pwp, buf, size_left);
22011425SBing.Hu@Sun.COM 	ASSERT(size_left >= n);
22111425SBing.Hu@Sun.COM 	buf += n; size_left -= n;
22211425SBing.Hu@Sun.COM 
22311425SBing.Hu@Sun.COM 	n = pmcs_dump_sspa_sregs(pwp, buf, size_left);
22411425SBing.Hu@Sun.COM 	ASSERT(size_left >= n);
22511425SBing.Hu@Sun.COM 	buf += n; size_left -= n;
22610696SDavid.Hollister@Sun.COM 	n = snprintf(buf, size_left, "\nDump firmware log: \n"
22710696SDavid.Hollister@Sun.COM 	    "-----------------\n");
22810696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
22910696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
23010696SDavid.Hollister@Sun.COM 
23110696SDavid.Hollister@Sun.COM 	n = pmcs_dump_fwlog(pwp, buf, size_left);
23210696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
23310696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
23410696SDavid.Hollister@Sun.COM 
23510696SDavid.Hollister@Sun.COM 	n = pmcs_dump_gsm(pwp, buf, size_left);
23610696SDavid.Hollister@Sun.COM 	ASSERT(size_left >= n);
23710696SDavid.Hollister@Sun.COM 	buf += n; size_left -= n;
23811425SBing.Hu@Sun.COM 
23911425SBing.Hu@Sun.COM 	n = snprintf(buf, size_left, "-----------------\n"
24011425SBing.Hu@Sun.COM 	    "\n------------ Dump internal registers end  -------------\n");
24111425SBing.Hu@Sun.COM 	ASSERT(size_left >= n);
24211425SBing.Hu@Sun.COM 	buf += n; size_left -= n;
24310696SDavid.Hollister@Sun.COM }
24410696SDavid.Hollister@Sun.COM 
24510696SDavid.Hollister@Sun.COM static int
pmcs_dump_fwlog(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)24610696SDavid.Hollister@Sun.COM pmcs_dump_fwlog(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
24710696SDavid.Hollister@Sun.COM {
24810696SDavid.Hollister@Sun.COM 	pmcs_fw_event_hdr_t *evl_hdr;
24910696SDavid.Hollister@Sun.COM 	int n = 0, retries = 0;
25010696SDavid.Hollister@Sun.COM 	uint32_t evlog_latest_idx;
25110696SDavid.Hollister@Sun.COM 	boolean_t log_is_current = B_FALSE;
25210696SDavid.Hollister@Sun.COM 
25310696SDavid.Hollister@Sun.COM 	if (pwp->fwlogp == NULL) {
25410696SDavid.Hollister@Sun.COM 		n = snprintf(buf, size_left, "\nFirmware logging "
25510696SDavid.Hollister@Sun.COM 		    "not enabled\n");
25610696SDavid.Hollister@Sun.COM 		return (n);
25710696SDavid.Hollister@Sun.COM 	}
25810696SDavid.Hollister@Sun.COM 
25910696SDavid.Hollister@Sun.COM 	/*
26010696SDavid.Hollister@Sun.COM 	 * First, check to make sure all entries have been DMAed to the
26110696SDavid.Hollister@Sun.COM 	 * log buffer.
26210696SDavid.Hollister@Sun.COM 	 *
26310696SDavid.Hollister@Sun.COM 	 * We'll wait the required 50ms, but if the latest entry keeps
26410696SDavid.Hollister@Sun.COM 	 * changing, we'll only retry twice
26510696SDavid.Hollister@Sun.COM 	 */
26610696SDavid.Hollister@Sun.COM 	evl_hdr = (pmcs_fw_event_hdr_t *)pwp->fwlogp;
26710696SDavid.Hollister@Sun.COM 	evlog_latest_idx = evl_hdr->fw_el_latest_idx;
26810696SDavid.Hollister@Sun.COM 
26910696SDavid.Hollister@Sun.COM 	while ((log_is_current == B_FALSE) && (retries < 3)) {
27010696SDavid.Hollister@Sun.COM 		drv_usecwait(50 * 1000);
27110696SDavid.Hollister@Sun.COM 		if (evl_hdr->fw_el_latest_idx == evlog_latest_idx) {
27210696SDavid.Hollister@Sun.COM 			log_is_current = B_TRUE;
27310696SDavid.Hollister@Sun.COM 		} else {
27410696SDavid.Hollister@Sun.COM 			++retries;
27511048SDavid.Hollister@Sun.COM 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
27610696SDavid.Hollister@Sun.COM 			    "%s: event log is still being updated... waiting",
27710696SDavid.Hollister@Sun.COM 			    __func__);
27810696SDavid.Hollister@Sun.COM 			evlog_latest_idx = evl_hdr->fw_el_latest_idx;
27910696SDavid.Hollister@Sun.COM 		}
28010696SDavid.Hollister@Sun.COM 	}
28110696SDavid.Hollister@Sun.COM 
28210696SDavid.Hollister@Sun.COM 	n = pmcs_dump_binary(pwp, pwp->fwlogp, 0, (PMCS_FWLOG_SIZE >> 2),
28310696SDavid.Hollister@Sun.COM 	    buf, size_left);
28410696SDavid.Hollister@Sun.COM 
28510696SDavid.Hollister@Sun.COM 	return (n);
28610696SDavid.Hollister@Sun.COM }
28710696SDavid.Hollister@Sun.COM 
28810696SDavid.Hollister@Sun.COM /*
28910696SDavid.Hollister@Sun.COM  * Dump Inbound and Outbound Queues.
29010696SDavid.Hollister@Sun.COM  */
29110696SDavid.Hollister@Sun.COM static int
pmcs_dump_ioqs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)29210696SDavid.Hollister@Sun.COM pmcs_dump_ioqs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
29310696SDavid.Hollister@Sun.COM {
29410696SDavid.Hollister@Sun.COM 	uint8_t i = 0, k = 0;
29510696SDavid.Hollister@Sun.COM 	uint32_t j = 0, depth = 0;
29610696SDavid.Hollister@Sun.COM 	int n = 0;
29710696SDavid.Hollister@Sun.COM 	uint32_t *ptr = NULL;
29810696SDavid.Hollister@Sun.COM 
29910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump I/O queues: \n"
30010696SDavid.Hollister@Sun.COM 	    "-----------------\n");
30110696SDavid.Hollister@Sun.COM 	for (i = 0; i < PMCS_NIQ; i++) {
30210696SDavid.Hollister@Sun.COM 		depth = PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i)));
30310696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
30410696SDavid.Hollister@Sun.COM 		    "IQ[%d] Details:\n-----------------\n", i);
30510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
30610696SDavid.Hollister@Sun.COM 		    "    depth = 0x%04x\n", depth);
30710696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
30810696SDavid.Hollister@Sun.COM 		    "    latest ci = 0x%02x\n", pmcs_rd_iqci(pwp, i));
30910696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
31010696SDavid.Hollister@Sun.COM 		    "    latest pi = 0x%02x\n", pmcs_rd_iqpi(pwp, i));
31110696SDavid.Hollister@Sun.COM 		for (j = 0; j < depth; j++) {
31210696SDavid.Hollister@Sun.COM 			n += snprintf(&buf[n], (size_left - n),
31310696SDavid.Hollister@Sun.COM 			    "IOMB[%d]:\n", j);
31410696SDavid.Hollister@Sun.COM 			ptr = &pwp->iqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
31510696SDavid.Hollister@Sun.COM 			for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
31610696SDavid.Hollister@Sun.COM 			    k += 8) {
31710696SDavid.Hollister@Sun.COM 				n += snprintf(&buf[n], (size_left - n),
31810696SDavid.Hollister@Sun.COM 				    "0x%08x 0x%08x 0x%08x 0x%08x "
31910696SDavid.Hollister@Sun.COM 				    "0x%08x 0x%08x 0x%08x 0x%08x\n",
32010696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k]), LE_32(ptr[k+1]),
32110696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
32210696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
32310696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
32410696SDavid.Hollister@Sun.COM 			}
32510696SDavid.Hollister@Sun.COM 		}
32610696SDavid.Hollister@Sun.COM 	}
32710696SDavid.Hollister@Sun.COM 	for (i = 0; i < PMCS_NOQ; i++) {
32810696SDavid.Hollister@Sun.COM 		depth = PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i)));
32910696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
33010696SDavid.Hollister@Sun.COM 		    "OQ[%d] Details:\n", i);
33110696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
33210696SDavid.Hollister@Sun.COM 		    "    depth = 0x%04x\n", depth);
33310696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
33410696SDavid.Hollister@Sun.COM 		    "    latest ci = 0x%02x\n", pmcs_rd_oqci(pwp, i));
33510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n),
33610696SDavid.Hollister@Sun.COM 		    "    latest pi = 0x%02x\n", pmcs_rd_oqpi(pwp, i));
33710696SDavid.Hollister@Sun.COM 		for (j = 0; j < depth; j++) {
33810696SDavid.Hollister@Sun.COM 			n += snprintf(&buf[n], (size_left - n),
33910696SDavid.Hollister@Sun.COM 			    "IOMB[%d]:\n", j);
34010696SDavid.Hollister@Sun.COM 			ptr = &pwp->oqp[i][(j * PMCS_QENTRY_SIZE) >> 2];
34110696SDavid.Hollister@Sun.COM 			for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
34210696SDavid.Hollister@Sun.COM 			    k += 8) {
34310696SDavid.Hollister@Sun.COM 				n += snprintf(&buf[n], (size_left - n),
34410696SDavid.Hollister@Sun.COM 				    "0x%08x 0x%08x 0x%08x 0x%08x "
34510696SDavid.Hollister@Sun.COM 				    "0x%08x 0x%08x 0x%08x 0x%08x\n",
34610696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k]), LE_32(ptr[k+1]),
34710696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
34810696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
34910696SDavid.Hollister@Sun.COM 				    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
35010696SDavid.Hollister@Sun.COM 			}
35110696SDavid.Hollister@Sun.COM 		}
35210696SDavid.Hollister@Sun.COM 
35310696SDavid.Hollister@Sun.COM 	}
35410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
35510696SDavid.Hollister@Sun.COM 	    "Dump I/O queues end \n");
35610696SDavid.Hollister@Sun.COM 	return (n);
35710696SDavid.Hollister@Sun.COM }
35810696SDavid.Hollister@Sun.COM 
35910696SDavid.Hollister@Sun.COM /*
36010696SDavid.Hollister@Sun.COM  * Dump SPC Version.
36110696SDavid.Hollister@Sun.COM  */
36210696SDavid.Hollister@Sun.COM static int
pmcs_dump_spc_ver(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)36310696SDavid.Hollister@Sun.COM pmcs_dump_spc_ver(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
36410696SDavid.Hollister@Sun.COM {
36510696SDavid.Hollister@Sun.COM 	int n = 0;
36610696SDavid.Hollister@Sun.COM 
36710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump SPC version: \n"
36810696SDavid.Hollister@Sun.COM 	    "-----------------\n");
36910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
37010696SDavid.Hollister@Sun.COM 	    "0x%02x\n", PMCS_FW_TYPE(pwp));
37110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "    Sub-Minor Release "
37210696SDavid.Hollister@Sun.COM 	    "Number = 0x%02x\n", PMCS_FW_MICRO(pwp));
37310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "    Minor Release "
37410696SDavid.Hollister@Sun.COM 	    "Number = 0x%02x\n", PMCS_FW_MINOR(pwp));
37510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "    Major Release "
37610696SDavid.Hollister@Sun.COM 	    "Number = 0x%02x\n", PMCS_FW_MAJOR(pwp));
37710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "SPC DeviceID = 0x%04x\n",
37810696SDavid.Hollister@Sun.COM 	    pmcs_rd_topunit(pwp, PMCS_SPC_DEVICE_ID));
37910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "SPC Device Revision = "
38010696SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION));
38110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "SPC BootStrap Register = "
38210696SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_topunit(pwp, PMCS_SPC_BOOT_STRAP));
38310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "SPC Reset Register = 0x%08x\n",
38410696SDavid.Hollister@Sun.COM 	    pmcs_rd_topunit(pwp, PMCS_SPC_RESET));
38510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
38610696SDavid.Hollister@Sun.COM 	    "Dump SPC version end \n");
38710696SDavid.Hollister@Sun.COM 	return (n);
38810696SDavid.Hollister@Sun.COM }
38910696SDavid.Hollister@Sun.COM 
39010696SDavid.Hollister@Sun.COM /*
39110696SDavid.Hollister@Sun.COM  * Dump MPI Table.
39210696SDavid.Hollister@Sun.COM  */
39310696SDavid.Hollister@Sun.COM static int
pmcs_dump_mpi_table(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)39410696SDavid.Hollister@Sun.COM pmcs_dump_mpi_table(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
39510696SDavid.Hollister@Sun.COM {
39610696SDavid.Hollister@Sun.COM 	int n = 0;
39710696SDavid.Hollister@Sun.COM 
39810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump MSGU registers: \n"
39910696SDavid.Hollister@Sun.COM 	    "-----------------\n");
40010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "inb_doorbell = 0x%08x\n",
40110696SDavid.Hollister@Sun.COM 	    pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB));
40210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "inb_doorbell_clear = 0x%08x"
40310696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR));
40410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell = 0x%08x"
40510696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB));
40610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell_clear = 0x%08x"
40710696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR));
40810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "scratch_pad0 = 0x%08x"
40910696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0));
41010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "scratch_pad1 = 0x%08x"
41110696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1));
41210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "scratch_pad2 = 0x%08x"
41310696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2));
41410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "scratch_pad3 = 0x%08x"
41510696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3));
41610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad0 = 0x%08x"
41710696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0));
41810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad1 = 0x%08x"
41910696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH1));
42010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad2 = 0x%08x"
42110696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH2));
42210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad3 = 0x%08x"
42310696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH3));
42410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad4 = 0x%08x"
42510696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH4));
42610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad5 = 0x%08x"
42710696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH5));
42810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad6 = 0x%08x"
42910696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH6));
43010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "host_scratch_pad7 = 0x%08x"
43110696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH7));
43210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "outb_doorbell_mask = 0x%08x"
43310696SDavid.Hollister@Sun.COM 	    "\n", pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK));
43410696SDavid.Hollister@Sun.COM 
43510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MPI Configuration Table: \n"
43610696SDavid.Hollister@Sun.COM 	    "-----------------\n");
43710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "ASCII Signature = 0x%08x\n",
43810696SDavid.Hollister@Sun.COM 	    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS));
43910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Type = "
44010696SDavid.Hollister@Sun.COM 	    "0x%08x\n", PMCS_FW_TYPE(pwp));
44110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Firmware Release Variant = "
44210696SDavid.Hollister@Sun.COM 	    "0x%08x\n", PMCS_FW_VARIANT(pwp));
44310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Firmware Sub-Minor Release "
44410696SDavid.Hollister@Sun.COM 	    "Number = 0x%08x\n", PMCS_FW_MICRO(pwp));
44510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Firmware Minor Release "
44610696SDavid.Hollister@Sun.COM 	    "Number = 0x%08x\n", PMCS_FW_MINOR(pwp));
44710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Firmware Major Release "
44810696SDavid.Hollister@Sun.COM 	    "Number = 0x%08x\n", PMCS_FW_MAJOR(pwp));
44910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Maximum Outstanding I/Os "
45010696SDavid.Hollister@Sun.COM 	    "supported = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO));
45110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Maximum Scatter-Gather List "
45210696SDavid.Hollister@Sun.COM 	    "Elements = 0x%08x\n",
45310696SDavid.Hollister@Sun.COM 	    PMCS_MSGL(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
45410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Maximum number of devices "
45510696SDavid.Hollister@Sun.COM 	    "connected to the SPC = 0x%08x\n",
45610696SDavid.Hollister@Sun.COM 	    PMCS_MD(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0)));
45710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Maximum Number of IQs "
45810696SDavid.Hollister@Sun.COM 	    "supported = 0x%08x\n",
45910696SDavid.Hollister@Sun.COM 	    PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
46010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Maximum Number of OQs "
46110696SDavid.Hollister@Sun.COM 	    "supported = 0x%08x\n",
46210696SDavid.Hollister@Sun.COM 	    PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
46310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "High Priority Queue supported"
46410696SDavid.Hollister@Sun.COM 	    " = 0x%08x\n", PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
46510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Interrupt Coalescing supported"
46610696SDavid.Hollister@Sun.COM 	    " = 0x%08x\n", PMCS_ICS(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
46710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Number of Phys = "
46810696SDavid.Hollister@Sun.COM 	    "0x%08x\n", PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
46910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "SAS Revision Specification = "
47010696SDavid.Hollister@Sun.COM 	    "0x%08x\n", PMCS_SASREV(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1)));
47110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "General Status Table Offset = "
47210696SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO));
47310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Configuration "
47410696SDavid.Hollister@Sun.COM 	    "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO));
47510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Outbound Queue Configuration "
47610696SDavid.Hollister@Sun.COM 	    "Table Offset = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO));
47710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Normal/High "
47810696SDavid.Hollister@Sun.COM 	    "Priority Processing Depth = 0x%02x 0x%02x\n",
47910696SDavid.Hollister@Sun.COM 	    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) & IQ_NORMAL_PRI_DEPTH_MASK),
48010696SDavid.Hollister@Sun.COM 	    ((pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
48110696SDavid.Hollister@Sun.COM 	    IQ_HIPRI_PRI_DEPTH_MASK) >> IQ_HIPRI_PRI_DEPTH_SHIFT));
48210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "General Event Notification "
48310696SDavid.Hollister@Sun.COM 	    "Queue = 0x%02x\n", (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
48410696SDavid.Hollister@Sun.COM 	    GENERAL_EVENT_OQ_MASK) >> GENERAL_EVENT_OQ_SHIFT);
48510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Device Handle Removed "
48610696SDavid.Hollister@Sun.COM 	    "Notification Queue = 0x%02x\n",
48710696SDavid.Hollister@Sun.COM 	    (uint32_t)(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO2) &
48810696SDavid.Hollister@Sun.COM 	    DEVICE_HANDLE_REMOVED_MASK) >> DEVICE_HANDLE_REMOVED_SHIFT);
48910696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < pwp->nphy; i++) {
49010696SDavid.Hollister@Sun.COM 		uint32_t woff = i / 4;
49110696SDavid.Hollister@Sun.COM 		uint32_t shf = (i % 4) * 8;
49210696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "SAS HW Event "
49310696SDavid.Hollister@Sun.COM 		    "Notification Queue - PHY ID %d = 0x%02x\n", i,
49410696SDavid.Hollister@Sun.COM 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_EVQS + (woff << 2)) >> shf)
49510696SDavid.Hollister@Sun.COM 		    & 0xff);
49610696SDavid.Hollister@Sun.COM 	}
49710696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < pwp->nphy; i++) {
49810696SDavid.Hollister@Sun.COM 		uint32_t woff = i / 4;
49910696SDavid.Hollister@Sun.COM 		uint32_t shf = (i % 4) * 8;
50010696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "SATA NCQ Error "
50110696SDavid.Hollister@Sun.COM 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
50210696SDavid.Hollister@Sun.COM 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SNCQ + (woff << 2)) >> shf)
50310696SDavid.Hollister@Sun.COM 		    & 0xff);
50410696SDavid.Hollister@Sun.COM 	}
50510696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < pwp->nphy; i++) {
50610696SDavid.Hollister@Sun.COM 		uint32_t woff = i / 4;
50710696SDavid.Hollister@Sun.COM 		uint32_t shf = (i % 4) * 8;
50810696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "I_T Nexus Target "
50910696SDavid.Hollister@Sun.COM 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
51010696SDavid.Hollister@Sun.COM 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IT_NTENQ +
51110696SDavid.Hollister@Sun.COM 		    (woff << 2)) >> shf) & 0xff);
51210696SDavid.Hollister@Sun.COM 	}
51310696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < pwp->nphy; i++) {
51410696SDavid.Hollister@Sun.COM 		uint32_t woff = i / 4;
51510696SDavid.Hollister@Sun.COM 		uint32_t shf = (i % 4) * 8;
51610696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "SSP Target "
51710696SDavid.Hollister@Sun.COM 		    "Event Notification Queue - PHY ID %d = 0x%02x\n", i,
51810696SDavid.Hollister@Sun.COM 		    (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SSP_TENQ +
51910696SDavid.Hollister@Sun.COM 		    (woff << 2)) >> shf) & 0xff);
52010696SDavid.Hollister@Sun.COM 	}
52111847SDavid.Hollister@Sun.COM 
52211847SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "I/O Abort Delay = 0x%04x\n",
52311847SDavid.Hollister@Sun.COM 	    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IOABTDLY) & 0xffff);
52411847SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
52511847SDavid.Hollister@Sun.COM 	    "Customization Setting = 0x%08x\n",
52611847SDavid.Hollister@Sun.COM 	    pmcs_rd_mpi_tbl(pwp, PMCS_MPI_CUSTSET));
52710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
52810696SDavid.Hollister@Sun.COM 	    "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAH));
52910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address "
53010696SDavid.Hollister@Sun.COM 	    "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAL));
53110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Size "
53210696SDavid.Hollister@Sun.COM 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBS));
53310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Severity "
53410696SDavid.Hollister@Sun.COM 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELSEV));
53510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
53610696SDavid.Hollister@Sun.COM 	    "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAH));
53710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Address "
53810696SDavid.Hollister@Sun.COM 	    "Lower = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBAL));
53910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Buffer Size "
54010696SDavid.Hollister@Sun.COM 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELBS));
54110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "IOP Event Log Severity "
54210696SDavid.Hollister@Sun.COM 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IELSEV));
54310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Fatal Error Interrupt "
54410696SDavid.Hollister@Sun.COM 	    "= 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR));
54510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
54610696SDavid.Hollister@Sun.COM 	    "Fatal Error Register Dump Offset "
54710696SDavid.Hollister@Sun.COM 	    "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU));
54810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
54910696SDavid.Hollister@Sun.COM 	    "Fatal Error Register Dump Length "
55010696SDavid.Hollister@Sun.COM 	    "For MSGU = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU));
55110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
55210696SDavid.Hollister@Sun.COM 	    "Fatal Error Register Dump Offset "
55310696SDavid.Hollister@Sun.COM 	    "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP));
55410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
55510696SDavid.Hollister@Sun.COM 	    "Fatal Error Register Dump Length "
55610696SDavid.Hollister@Sun.COM 	    "For IOP = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP));
55710696SDavid.Hollister@Sun.COM 
55810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Dump GS Table: \n"
55910696SDavid.Hollister@Sun.COM 	    "-----------------\n");
56010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),  "GST MPI State: 0x%08x\n",
56110696SDavid.Hollister@Sun.COM 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE));
56210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),  "Inbound Queue Freeze State 0 "
56310696SDavid.Hollister@Sun.COM 	    "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0));
56410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Inbound Queue Freeze State 1 "
56510696SDavid.Hollister@Sun.COM 	    "= 0x%08x\n", pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1));
56610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MSGU Tick Count = 0x%08x \n",
56710696SDavid.Hollister@Sun.COM 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK));
56810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "IOP Tick Count = 0x%08x\n",
56910696SDavid.Hollister@Sun.COM 	    pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK));
57010696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < pwp->nphy; i++) {
57110696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), " Phy %d state = "
57210696SDavid.Hollister@Sun.COM 		    "0x%08x\n", i, pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i)));
57310696SDavid.Hollister@Sun.COM 	}
57410696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < pwp->nphy; i++) {
57510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), " Recoverable Error "
57610696SDavid.Hollister@Sun.COM 		    "Information %d = 0x%08x\n", i,
57710696SDavid.Hollister@Sun.COM 		    pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i)));
57810696SDavid.Hollister@Sun.COM 	}
57910696SDavid.Hollister@Sun.COM 
58010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Dump IQCT Table\n"
58110696SDavid.Hollister@Sun.COM 	    "-----------------\n");
58210696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < PMCS_NIQ; i++) {
58310696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "Inbound Queue "
58410696SDavid.Hollister@Sun.COM 		    "Configuration Table - [%d]:\n", i);
58510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
58610696SDavid.Hollister@Sun.COM 		    "Depth = 0x%08x\n",
58710696SDavid.Hollister@Sun.COM 		    PMCS_IQDX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
58810696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
58910696SDavid.Hollister@Sun.COM 		    "Element Size and Priority = 0x%08x 0x%08x\n",
59010696SDavid.Hollister@Sun.COM 		    PMCS_IQESX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))),
59110696SDavid.Hollister@Sun.COM 		    PMCS_IQPX(pmcs_rd_iqc_tbl(pwp, PMCS_IQC_PARMX(i))));
59210696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
59310696SDavid.Hollister@Sun.COM 		    "Base Address High = 0x%08x\n",
59410696SDavid.Hollister@Sun.COM 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQBAHX(i)));
59510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
59610696SDavid.Hollister@Sun.COM 		    "Base Address Low = 0x%08x\n",
59710696SDavid.Hollister@Sun.COM 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQBALX(i)));
59810696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
59910696SDavid.Hollister@Sun.COM 		    "Consumer Index Base Address High = 0x%08x\n",
60010696SDavid.Hollister@Sun.COM 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBAHX(i)));
60110696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
60210696SDavid.Hollister@Sun.COM 		    "Consumer Index Base Address Low = 0x%08x\n",
60310696SDavid.Hollister@Sun.COM 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQCIBALX(i)));
60410696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
60510696SDavid.Hollister@Sun.COM 		    "Producer Index PCI BAR = 0x%08x\n",
60610696SDavid.Hollister@Sun.COM 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQPIBARX(i)));
60710696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Inbound Queue "
60810696SDavid.Hollister@Sun.COM 		    "Producer Index PCI BAR offset = 0x%08x\n",
60910696SDavid.Hollister@Sun.COM 		    pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i)));
61010696SDavid.Hollister@Sun.COM 	}
61110696SDavid.Hollister@Sun.COM 
61210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "Dump OQCT Table: \n"
61310696SDavid.Hollister@Sun.COM 	    "-----------------\n");
61410696SDavid.Hollister@Sun.COM 	for (uint8_t i = 0; i < PMCS_NOQ; i++) {
61510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "Outbound Queue "
61610696SDavid.Hollister@Sun.COM 		    "Configuration Table - [%d]:\n", i);
61710696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
61810696SDavid.Hollister@Sun.COM 		    "Depth = 0x%08x\n",
61910696SDavid.Hollister@Sun.COM 		    PMCS_OQDX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
62010696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
62110696SDavid.Hollister@Sun.COM 		    "Element Size = 0x%08x\n",
62210696SDavid.Hollister@Sun.COM 		    PMCS_OQESX(pmcs_rd_oqc_tbl(pwp, PMCS_OQC_PARMX(i))));
62310696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
62410696SDavid.Hollister@Sun.COM 		    "Base Address High = 0x%08x\n",
62510696SDavid.Hollister@Sun.COM 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQBAHX(i)));
62610696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
62710696SDavid.Hollister@Sun.COM 		    "Base Address Low = 0x%08x\n",
62810696SDavid.Hollister@Sun.COM 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQBALX(i)));
62910696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
63010696SDavid.Hollister@Sun.COM 		    "Producer Index Base Address High = 0x%08x\n",
63110696SDavid.Hollister@Sun.COM 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBAHX(i)));
63210696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
63310696SDavid.Hollister@Sun.COM 		    "Producer Index Base Address Low = 0x%08x\n",
63410696SDavid.Hollister@Sun.COM 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQPIBALX(i)));
63510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
63610696SDavid.Hollister@Sun.COM 		    "Consumer Index PCI BAR = 0x%08x\n",
63710696SDavid.Hollister@Sun.COM 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQCIBARX(i)));
63810696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
63910696SDavid.Hollister@Sun.COM 		    "Consumer Index PCI BAR offset = 0x%08x\n",
64010696SDavid.Hollister@Sun.COM 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i)));
64110696SDavid.Hollister@Sun.COM 
64210696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
64310696SDavid.Hollister@Sun.COM 		    "Interrupt Coalescing Timeout = 0x%08x\n",
64410696SDavid.Hollister@Sun.COM 		    PMCS_OQICT(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
64510696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
64610696SDavid.Hollister@Sun.COM 		    "Interrupt Coalescing Count = 0x%08x\n",
64710696SDavid.Hollister@Sun.COM 		    PMCS_OQICC(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
64810696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
64910696SDavid.Hollister@Sun.COM 		    "Interrupt Vector =  0x%08x\n",
65010696SDavid.Hollister@Sun.COM 		    PMCS_OQIV(pmcs_rd_oqc_tbl(pwp, PMCS_OQIPARM(i))));
65110696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "    Outbound Queue "
65210696SDavid.Hollister@Sun.COM 		    "Dynamic Interrupt Coalescing Timeout = 0x%08x\n",
65310696SDavid.Hollister@Sun.COM 		    pmcs_rd_oqc_tbl(pwp, PMCS_OQDICX(i)));
65410696SDavid.Hollister@Sun.COM 
65510696SDavid.Hollister@Sun.COM 	}
65610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
65710696SDavid.Hollister@Sun.COM 	    "Dump MPI Table end\n");
65810696SDavid.Hollister@Sun.COM 	return (n);
65910696SDavid.Hollister@Sun.COM }
66010696SDavid.Hollister@Sun.COM 
66110696SDavid.Hollister@Sun.COM /*ARGSUSED*/
66210696SDavid.Hollister@Sun.COM int
pmcs_dump_binary(pmcs_hw_t * pwp,uint32_t * addr,uint32_t off,uint32_t words_to_read,caddr_t buf,uint32_t size_left)66310696SDavid.Hollister@Sun.COM pmcs_dump_binary(pmcs_hw_t *pwp, uint32_t *addr, uint32_t off,
66410696SDavid.Hollister@Sun.COM     uint32_t words_to_read, caddr_t buf, uint32_t size_left)
66510696SDavid.Hollister@Sun.COM {
66610696SDavid.Hollister@Sun.COM 	uint32_t i;
66710696SDavid.Hollister@Sun.COM 	int n = 0;
66810696SDavid.Hollister@Sun.COM 	char c = ' ';
66910696SDavid.Hollister@Sun.COM 
67010696SDavid.Hollister@Sun.COM 	for (i = 0, n = 0; i < words_to_read; i++) {
67110696SDavid.Hollister@Sun.COM 		if ((i & 7) == 0) {
67210696SDavid.Hollister@Sun.COM 			n += snprintf(&buf[n], (size_left - n),
67310696SDavid.Hollister@Sun.COM 			    "%08x: ", (i << 2) + off);
67410696SDavid.Hollister@Sun.COM 		}
67510696SDavid.Hollister@Sun.COM 		if ((i + 1) & 7) {
67610696SDavid.Hollister@Sun.COM 			c = ' ';
67710696SDavid.Hollister@Sun.COM 		} else {
67810696SDavid.Hollister@Sun.COM 			c = '\n';
67910696SDavid.Hollister@Sun.COM 		}
68010696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "%08x%c", addr[i], c);
68110696SDavid.Hollister@Sun.COM 	}
68210696SDavid.Hollister@Sun.COM 	return (n);
68310696SDavid.Hollister@Sun.COM }
68410696SDavid.Hollister@Sun.COM 
68510696SDavid.Hollister@Sun.COM /*
68610696SDavid.Hollister@Sun.COM  * Dump Global Shared Memory Configuration Registers
68710696SDavid.Hollister@Sun.COM  */
68810696SDavid.Hollister@Sun.COM static int
pmcs_dump_gsm_conf(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)68910696SDavid.Hollister@Sun.COM pmcs_dump_gsm_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
69010696SDavid.Hollister@Sun.COM {
69110696SDavid.Hollister@Sun.COM 	int n = 0;
69210696SDavid.Hollister@Sun.COM 
69310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM configuration "
69410696SDavid.Hollister@Sun.COM 	    "registers: \n -----------------\n");
69510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "RB6 Access Register = "
69611980SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, RB6_ACCESS));
69710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "CFG and RST = 0x%08x\n",
69811980SDavid.Hollister@Sun.COM 	    pmcs_rd_gsm_reg(pwp, 0, GSM_CFG_AND_RESET));
69910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "RAM ECC ERR INDICATOR= "
70011980SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0,
70111980SDavid.Hollister@Sun.COM 	    RAM_ECC_DOUBLE_ERROR_INDICATOR));
70210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "READ ADR PARITY CHK EN = "
70311980SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_CHK_EN));
70410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "WRITE ADR PARITY CHK EN = "
70511980SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_CHK_EN));
70610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "WRITE DATA PARITY CHK EN= "
70711980SDavid.Hollister@Sun.COM 	    "0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_CHK_EN));
70810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
70910696SDavid.Hollister@Sun.COM 	    "READ ADR PARITY ERROR INDICATOR = 0x%08x\n",
71011980SDavid.Hollister@Sun.COM 	    pmcs_rd_gsm_reg(pwp, 0, READ_ADR_PARITY_ERROR_INDICATOR));
71110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
71210696SDavid.Hollister@Sun.COM 	    "WRITE ADR PARITY ERROR INDICATOR = 0x%08x\n",
71311980SDavid.Hollister@Sun.COM 	    pmcs_rd_gsm_reg(pwp, 0, WRITE_ADR_PARITY_ERROR_INDICATOR));
71410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
71510696SDavid.Hollister@Sun.COM 	    "WRITE DATA PARITY ERROR INDICATOR = 0x%08x\n",
71611980SDavid.Hollister@Sun.COM 	    pmcs_rd_gsm_reg(pwp, 0, WRITE_DATA_PARITY_ERROR_INDICATOR));
71710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 IOP Register"
71811980SDavid.Hollister@Sun.COM 	    " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, NMI_EN_VPE0_IOP));
71910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "NMI Enable VPE0 AAP1 Register"
72011980SDavid.Hollister@Sun.COM 	    " = 0x%08x\n", pmcs_rd_gsm_reg(pwp, 0, NMI_EN_VPE0_AAP1));
72110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
72210696SDavid.Hollister@Sun.COM 	    "Dump GSM configuration registers end \n");
72310696SDavid.Hollister@Sun.COM 	return (n);
72410696SDavid.Hollister@Sun.COM }
72510696SDavid.Hollister@Sun.COM 
72610696SDavid.Hollister@Sun.COM /*
72710696SDavid.Hollister@Sun.COM  * Dump PCIe Configuration Registers.
72810696SDavid.Hollister@Sun.COM  */
72910696SDavid.Hollister@Sun.COM static int
pmcs_dump_pcie_conf(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)73010696SDavid.Hollister@Sun.COM pmcs_dump_pcie_conf(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
73110696SDavid.Hollister@Sun.COM {
73210696SDavid.Hollister@Sun.COM 	int n = 0;
73310696SDavid.Hollister@Sun.COM 	uint32_t i = 0;
73410696SDavid.Hollister@Sun.COM 
73510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump PCIe configuration "
73610696SDavid.Hollister@Sun.COM 	    "registers: \n -----------------\n");
73710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "VENID = 0x%04x\n",
73810696SDavid.Hollister@Sun.COM 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_VENID));
73910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "DEVICE_ID = 0x%04x\n",
74010696SDavid.Hollister@Sun.COM 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_DEVID));
74110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "CFGCMD = 0x%04x\n",
74210696SDavid.Hollister@Sun.COM 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_COMM));
74310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "CFGSTAT = 0x%04x\n",
74410696SDavid.Hollister@Sun.COM 	    pci_config_get16(pwp->pci_acc_handle, PCI_CONF_STAT));
74510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "CLSCODE and REVID = 0x%08x\n",
74610696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_REVID));
74710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "BIST HDRTYPE LATTIM CLSIZE = "
74810696SDavid.Hollister@Sun.COM 	    "0x%08x\n",
74910696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_CACHE_LINESZ));
75010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-I LOWER = 0x%08x\n",
75110696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE0));
75210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-I UPPER = 0x%08x\n",
75310696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE1));
75410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-II LOWER = 0x%08x\n",
75510696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE2));
75610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-II UPPER = 0x%08x\n",
75710696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE3));
75810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-III = 0x%08x\n",
75910696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE4));
76010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MEMBASE-IV = 0x%08x\n",
76110696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_BASE5));
76210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "SVID = 0x%08x\n",
76310696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_SUBVENID));
76410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "ROMBASE = 0x%08x\n",
76510696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ROM));
76610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "CAP_PTR = 0x%02x\n",
76710696SDavid.Hollister@Sun.COM 	    pci_config_get8(pwp->pci_acc_handle, PCI_CONF_CAP_PTR));
76810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MAXLAT MINGNT INTPIN "
76910696SDavid.Hollister@Sun.COM 	    "INTLINE = 0x%08x\n",
77010696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PCI_CONF_ILINE));
77110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "PMC PM_NEXT_CAP PM_CAP_ID = "
77210696SDavid.Hollister@Sun.COM 	    "0x%08x\n", pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMC));
77310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "PMCSR = 0x%08x\n",
77410696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PMCSR));
77510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
77610696SDavid.Hollister@Sun.COM 	    "MC MSI_NEXT_CAP MSI_CAP_ID = 0x%08x\n",
77710696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSI));
77810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MAL = 0x%08x\n",
77910696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAL));
78010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MAU = 0x%08x\n",
78110696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MAU));
78210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MD = 0x%04x\n",
78310696SDavid.Hollister@Sun.COM 	    pci_config_get16(pwp->pci_acc_handle, PMCS_PCI_MD));
78410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
78510696SDavid.Hollister@Sun.COM 	    "PCIE_CAP PCIE_NEXT_CAP PCIE_CAP_ID = 0x%08x\n",
78610696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE));
78710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "DEVICE_CAP = 0x%08x\n",
78810696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CAP));
78910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
79010696SDavid.Hollister@Sun.COM 	    "DEVICE_STAT DEVICE_CTRL = 0x%08x\n",
79110696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_DEV_CTRL));
79210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "LINK_CAP = 0x%08x\n",
79310696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CAP));
79410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n),
79510696SDavid.Hollister@Sun.COM 	    "LINK_STAT LINK_CTRL = 0x%08x\n",
79610696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_LINK_CTRL));
79710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "MSIX_CAP = 0x%08x\n",
79810696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_MSIX_CAP));
79910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "TBL_OFFSET = 0x%08x\n",
80010696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_TBL_OFFSET));
80110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "PBA_OFFSET = 0x%08x\n",
80210696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PBA_OFFSET));
80310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "PCIE_CAP_HD = 0x%08x\n",
80410696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_PCIE_CAP_HD));
80510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "UE_STAT = 0x%08x\n",
80610696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_STAT));
80710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "UE_MASK = 0x%08x\n",
80810696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_MASK));
80910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "UE_SEV = 0x%08x\n",
81010696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_UE_SEV));
81110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "CE_STAT = 0x%08x\n",
81210696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_STAT));
81310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "CE_MASK = 0x%08x\n",
81410696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_CE_MASK));
81510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "ADV_ERR_CTRL = 0x%08x\n",
81610696SDavid.Hollister@Sun.COM 	    pci_config_get32(pwp->pci_acc_handle, PMCS_PCI_ADV_ERR_CTRL));
81710696SDavid.Hollister@Sun.COM 	for (i = 0; i < 4; i++) {
81810696SDavid.Hollister@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "HD_LOG_DW%d = "
81910696SDavid.Hollister@Sun.COM 		    "0x%08x\n", i, pci_config_get32(pwp->pci_acc_handle,
82010696SDavid.Hollister@Sun.COM 		    (PMCS_PCI_HD_LOG_DW + i * 4)));
82110696SDavid.Hollister@Sun.COM 	}
82210696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
82310696SDavid.Hollister@Sun.COM 	    "Dump PCIe configuration registers end \n");
82410696SDavid.Hollister@Sun.COM 	return (n);
82510696SDavid.Hollister@Sun.COM }
82610696SDavid.Hollister@Sun.COM /*
82710696SDavid.Hollister@Sun.COM  * Called with axil_lock held
82810696SDavid.Hollister@Sun.COM  */
82910696SDavid.Hollister@Sun.COM static boolean_t
pmcs_shift_axil(pmcs_hw_t * pwp,uint32_t offset)83010696SDavid.Hollister@Sun.COM pmcs_shift_axil(pmcs_hw_t *pwp, uint32_t offset)
83110696SDavid.Hollister@Sun.COM {
83210696SDavid.Hollister@Sun.COM 	uint32_t newaxil = offset & ~GSM_BASE_MASK;
83310696SDavid.Hollister@Sun.COM 
83410696SDavid.Hollister@Sun.COM 	ASSERT(mutex_owned(&pwp->axil_lock));
83510696SDavid.Hollister@Sun.COM 	ddi_put32(pwp->top_acc_handle,
83610696SDavid.Hollister@Sun.COM 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
83710696SDavid.Hollister@Sun.COM 	drv_usecwait(10);
83810696SDavid.Hollister@Sun.COM 
83910696SDavid.Hollister@Sun.COM 	if (ddi_get32(pwp->top_acc_handle,
84010696SDavid.Hollister@Sun.COM 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
84111048SDavid.Hollister@Sun.COM 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
84211048SDavid.Hollister@Sun.COM 		    "AXIL register update failed");
84310696SDavid.Hollister@Sun.COM 		return (B_FALSE);
84410696SDavid.Hollister@Sun.COM 	}
84510696SDavid.Hollister@Sun.COM 	return (B_TRUE);
84610696SDavid.Hollister@Sun.COM }
84710696SDavid.Hollister@Sun.COM 
84810696SDavid.Hollister@Sun.COM static uint32_t
pmcs_get_axil(pmcs_hw_t * pwp)84910696SDavid.Hollister@Sun.COM pmcs_get_axil(pmcs_hw_t *pwp)
85010696SDavid.Hollister@Sun.COM {
85110696SDavid.Hollister@Sun.COM 	uint32_t regval = 0;
85210696SDavid.Hollister@Sun.COM 	mutex_enter(&pwp->axil_lock);
85310696SDavid.Hollister@Sun.COM 	regval = ddi_get32(pwp->top_acc_handle,
85410696SDavid.Hollister@Sun.COM 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
85510696SDavid.Hollister@Sun.COM 	mutex_exit(&pwp->axil_lock);
85610696SDavid.Hollister@Sun.COM 	return (regval);
85710696SDavid.Hollister@Sun.COM }
85810696SDavid.Hollister@Sun.COM 
85910696SDavid.Hollister@Sun.COM static void
pmcs_restore_axil(pmcs_hw_t * pwp,uint32_t oldaxil)86010696SDavid.Hollister@Sun.COM pmcs_restore_axil(pmcs_hw_t *pwp, uint32_t oldaxil)
86110696SDavid.Hollister@Sun.COM {
86210696SDavid.Hollister@Sun.COM 	mutex_enter(&pwp->axil_lock);
86310696SDavid.Hollister@Sun.COM 	ddi_put32(pwp->top_acc_handle,
86410696SDavid.Hollister@Sun.COM 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
86510696SDavid.Hollister@Sun.COM 	drv_usecwait(10);
86610696SDavid.Hollister@Sun.COM 
86710696SDavid.Hollister@Sun.COM 	if (ddi_get32(pwp->top_acc_handle,
86810696SDavid.Hollister@Sun.COM 	    &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
86911048SDavid.Hollister@Sun.COM 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
87011048SDavid.Hollister@Sun.COM 		    "AXIL register restore failed");
87110696SDavid.Hollister@Sun.COM 	}
87210696SDavid.Hollister@Sun.COM 	mutex_exit(&pwp->axil_lock);
87310696SDavid.Hollister@Sun.COM }
87410696SDavid.Hollister@Sun.COM 
87510696SDavid.Hollister@Sun.COM /*
87611425SBing.Hu@Sun.COM  * Dump Additional GSM Registers.
87711425SBing.Hu@Sun.COM  */
87811425SBing.Hu@Sun.COM static int
pmcs_dump_gsm_addiregs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)87911425SBing.Hu@Sun.COM pmcs_dump_gsm_addiregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
88011425SBing.Hu@Sun.COM {
88111425SBing.Hu@Sun.COM 	uint32_t i = 0;
88211425SBing.Hu@Sun.COM 	int n = 0, j = 0, nums = 0;
88311425SBing.Hu@Sun.COM 	uint32_t gsm_addr = 0, addr = 0;
88411425SBing.Hu@Sun.COM 
88511425SBing.Hu@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM Sparse Registers:"
88611425SBing.Hu@Sun.COM 	    "\n-----------------\n");
88711425SBing.Hu@Sun.COM 	for (i = 0; i < sizeof (gsm_spregs) / sizeof (pmcs_sparse_regs_t);
88811425SBing.Hu@Sun.COM 	    i++) {
88911425SBing.Hu@Sun.COM 		gsm_addr =
89011425SBing.Hu@Sun.COM 		    gsm_spregs[i].shift_addr + gsm_spregs[i].offset_start;
89111425SBing.Hu@Sun.COM 		nums = gsm_spregs[i].offset_end - gsm_spregs[i].offset_start;
89211425SBing.Hu@Sun.COM 		if (gsm_spregs[i].flag & PMCS_SPREGS_BLOCK_START) {
89311425SBing.Hu@Sun.COM 			n += snprintf(&buf[n], (size_left - n), "\n%s - 0x%08X"
89411425SBing.Hu@Sun.COM 			    "[MEMBASE-III SHIFT = 0x%08X]\nOffset:\n",
89511425SBing.Hu@Sun.COM 			    gsm_spregs[i].desc ? gsm_spregs[i].desc : "NULL",
89611425SBing.Hu@Sun.COM 			    gsm_spregs[i].base_addr, gsm_spregs[i].shift_addr);
89711425SBing.Hu@Sun.COM 		}
89811425SBing.Hu@Sun.COM 
89911425SBing.Hu@Sun.COM 		if (nums == 0) {
90011425SBing.Hu@Sun.COM 			n += snprintf(&buf[n], (size_left - n),
90111425SBing.Hu@Sun.COM 			    "[%04X]: %08X\n", gsm_spregs[i].offset_start,
90211980SDavid.Hollister@Sun.COM 			    pmcs_rd_gsm_reg(pwp, 0, gsm_addr));
90311425SBing.Hu@Sun.COM 		} else if (nums > 0) {
90411425SBing.Hu@Sun.COM 			n += snprintf(&buf[n], (size_left - n),
90511425SBing.Hu@Sun.COM 			    "\n[%04X] - [%04X]: \n", gsm_spregs[i].offset_start,
90611425SBing.Hu@Sun.COM 			    gsm_spregs[i].offset_end);
90711425SBing.Hu@Sun.COM 
90811425SBing.Hu@Sun.COM 			j = 0;
90911425SBing.Hu@Sun.COM 			while (nums > 0) {
91011425SBing.Hu@Sun.COM 				addr = gsm_addr + j * 4;
91111425SBing.Hu@Sun.COM 				n += snprintf(&buf[n], (size_left - n),
91211425SBing.Hu@Sun.COM 				    "[%04X]: %08X\n", addr & GSM_BASE_MASK,
91311980SDavid.Hollister@Sun.COM 				    pmcs_rd_gsm_reg(pwp, 0, addr));
91411425SBing.Hu@Sun.COM 				j++;
91511425SBing.Hu@Sun.COM 				nums -= 4;
91611425SBing.Hu@Sun.COM 			}
91711425SBing.Hu@Sun.COM 		}
91811425SBing.Hu@Sun.COM 
91911425SBing.Hu@Sun.COM 	}
92011425SBing.Hu@Sun.COM 
92111425SBing.Hu@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
92211425SBing.Hu@Sun.COM 	    "------------ Dump GSM Sparse Registers end ------------\n");
92311425SBing.Hu@Sun.COM 	return (n);
92411425SBing.Hu@Sun.COM 
92511425SBing.Hu@Sun.COM }
92611425SBing.Hu@Sun.COM 
92711425SBing.Hu@Sun.COM /*
92810696SDavid.Hollister@Sun.COM  * Dump GSM Memory Regions.
92910696SDavid.Hollister@Sun.COM  */
93010696SDavid.Hollister@Sun.COM static int
pmcs_dump_gsm(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)93110696SDavid.Hollister@Sun.COM pmcs_dump_gsm(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
93210696SDavid.Hollister@Sun.COM {
93310696SDavid.Hollister@Sun.COM 	int n = 0;
93410696SDavid.Hollister@Sun.COM 	uint32_t i = 0;
93510696SDavid.Hollister@Sun.COM 	uint32_t oldaxil = 0;
93610696SDavid.Hollister@Sun.COM 	uint32_t gsm_addr = 0;
93710696SDavid.Hollister@Sun.COM 	uint32_t *local_buf = NULL;
93810696SDavid.Hollister@Sun.COM 
93910696SDavid.Hollister@Sun.COM 	local_buf = kmem_zalloc(GSM_SM_BLKSZ, KM_NOSLEEP);
94010696SDavid.Hollister@Sun.COM 	if (local_buf == NULL) {
94111048SDavid.Hollister@Sun.COM 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
94210696SDavid.Hollister@Sun.COM 		    "%s: local_buf memory not allocated", __func__);
94310696SDavid.Hollister@Sun.COM 		return (0);
94410696SDavid.Hollister@Sun.COM 	}
94510696SDavid.Hollister@Sun.COM 
94610696SDavid.Hollister@Sun.COM 	oldaxil = pmcs_get_axil(pwp);
94710696SDavid.Hollister@Sun.COM 	mutex_enter(&pwp->axil_lock);
94810696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM IO Status Table: \n"
94910696SDavid.Hollister@Sun.COM 	    " -----------------\n");
95010696SDavid.Hollister@Sun.COM 	for (i = 0; i < 4; i++) {
95110696SDavid.Hollister@Sun.COM 		gsm_addr = IO_STATUS_TABLE_BASE + GSM_SM_BLKSZ * i;
95210696SDavid.Hollister@Sun.COM 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
95310696SDavid.Hollister@Sun.COM 			gsm_addr &= GSM_BASE_MASK;
95410696SDavid.Hollister@Sun.COM 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
95510696SDavid.Hollister@Sun.COM 			    &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
95610696SDavid.Hollister@Sun.COM 			    DDI_DEV_AUTOINCR);
95710696SDavid.Hollister@Sun.COM 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
95810696SDavid.Hollister@Sun.COM 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
95910696SDavid.Hollister@Sun.COM 		}
96010696SDavid.Hollister@Sun.COM 	}
96110696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
96210696SDavid.Hollister@Sun.COM 	    "Dump GSM IO Status Table end \n");
96310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Storage: \n"
96410696SDavid.Hollister@Sun.COM 	    " -----------------\n");
96510696SDavid.Hollister@Sun.COM 	for (i = 0; i < 2; i++) {
96610696SDavid.Hollister@Sun.COM 		gsm_addr = RING_BUF_STORAGE_0 + GSM_SM_BLKSZ * i;
96710696SDavid.Hollister@Sun.COM 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
96810696SDavid.Hollister@Sun.COM 			gsm_addr &= GSM_BASE_MASK;
96910696SDavid.Hollister@Sun.COM 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
97010696SDavid.Hollister@Sun.COM 			    &pwp->gsm_regs[gsm_addr >> 2], GSM_SM_BLKSZ >> 2,
97110696SDavid.Hollister@Sun.COM 			    DDI_DEV_AUTOINCR);
97210696SDavid.Hollister@Sun.COM 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
97310696SDavid.Hollister@Sun.COM 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
97410696SDavid.Hollister@Sun.COM 		}
97510696SDavid.Hollister@Sun.COM 	}
97610696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
97710696SDavid.Hollister@Sun.COM 	    "Dump Ring Buffer Storage end \n");
97810696SDavid.Hollister@Sun.COM 
97910696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Pointers:\n"
98010696SDavid.Hollister@Sun.COM 	    " -----------------\n");
98110696SDavid.Hollister@Sun.COM 		gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_PTR_OFF;
98210696SDavid.Hollister@Sun.COM 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
98310696SDavid.Hollister@Sun.COM 			gsm_addr &= GSM_BASE_MASK;
98410696SDavid.Hollister@Sun.COM 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
98510696SDavid.Hollister@Sun.COM 			    &pwp->gsm_regs[gsm_addr >> 2],
98610696SDavid.Hollister@Sun.COM 			    RING_BUF_PTR_SIZE >> 2, DDI_DEV_AUTOINCR);
98710696SDavid.Hollister@Sun.COM 			n += pmcs_dump_binary(pwp, local_buf, 0,
98810696SDavid.Hollister@Sun.COM 			    RING_BUF_PTR_SIZE >> 2, &buf[n], size_left - n);
98910696SDavid.Hollister@Sun.COM 		}
99010696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
99110696SDavid.Hollister@Sun.COM 	    "Dump Ring Buffer Pointers end \n");
99210696SDavid.Hollister@Sun.COM 
99310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump Ring Buffer Access: \n"
99410696SDavid.Hollister@Sun.COM 	    " -----------------\n");
99510696SDavid.Hollister@Sun.COM 		gsm_addr = RING_BUF_PTR_ACC_BASE + RING_BUF_ACC_OFF;
99610696SDavid.Hollister@Sun.COM 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
99710696SDavid.Hollister@Sun.COM 			gsm_addr &= GSM_BASE_MASK;
99810696SDavid.Hollister@Sun.COM 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
99910696SDavid.Hollister@Sun.COM 			    &pwp->gsm_regs[gsm_addr >> 2],
100010696SDavid.Hollister@Sun.COM 			    RING_BUF_ACC_SIZE >> 2, DDI_DEV_AUTOINCR);
100110696SDavid.Hollister@Sun.COM 			n += pmcs_dump_binary(pwp, local_buf, 0,
100210696SDavid.Hollister@Sun.COM 			    RING_BUF_ACC_SIZE >> 2, &buf[n], size_left - n);
100310696SDavid.Hollister@Sun.COM 		}
100410696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
100510696SDavid.Hollister@Sun.COM 	    "Dump Ring Buffer Access end \n");
100610696SDavid.Hollister@Sun.COM 
100710696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nDump GSM SM: \n"
100810696SDavid.Hollister@Sun.COM 	    " -----------------\n");
100910696SDavid.Hollister@Sun.COM 	for (i = 0; i < 16; i++) {
101010696SDavid.Hollister@Sun.COM 		gsm_addr = GSM_SM_BASE + GSM_SM_BLKSZ * i;
101110696SDavid.Hollister@Sun.COM 		if (pmcs_shift_axil(pwp, gsm_addr) == B_TRUE) {
101210696SDavid.Hollister@Sun.COM 			gsm_addr &= GSM_BASE_MASK;
101310696SDavid.Hollister@Sun.COM 			ddi_rep_get32(pwp->gsm_acc_handle, local_buf,
101410696SDavid.Hollister@Sun.COM 			    &pwp->gsm_regs[gsm_addr >> 2],
101510696SDavid.Hollister@Sun.COM 			    GSM_SM_BLKSZ >> 2, DDI_DEV_AUTOINCR);
101610696SDavid.Hollister@Sun.COM 			n += pmcs_dump_binary(pwp, local_buf, i * GSM_SM_BLKSZ,
101710696SDavid.Hollister@Sun.COM 			    GSM_SM_BLKSZ >> 2, &buf[n], size_left - n);
101810696SDavid.Hollister@Sun.COM 		}
101910696SDavid.Hollister@Sun.COM 	}
102010696SDavid.Hollister@Sun.COM 	mutex_exit(&pwp->axil_lock);
102110696SDavid.Hollister@Sun.COM 	pmcs_restore_axil(pwp, oldaxil);
102210696SDavid.Hollister@Sun.COM 
102310696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\n-----------------\n"
102410696SDavid.Hollister@Sun.COM 	    "Dump GSM SM end \n");
102510696SDavid.Hollister@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "-----------------\n"
102610696SDavid.Hollister@Sun.COM 	    "\n------------ Dump GSM Memory Regions end  -------------\n");
102710696SDavid.Hollister@Sun.COM 	if (local_buf) {
102810696SDavid.Hollister@Sun.COM 		kmem_free(local_buf, GSM_SM_BLKSZ);
102910696SDavid.Hollister@Sun.COM 	}
103010696SDavid.Hollister@Sun.COM 	return (n);
103110696SDavid.Hollister@Sun.COM }
103210696SDavid.Hollister@Sun.COM 
103310696SDavid.Hollister@Sun.COM /*
103410696SDavid.Hollister@Sun.COM  * Trace current Inbound Message host sent to SPC.
103510696SDavid.Hollister@Sun.COM  */
103610696SDavid.Hollister@Sun.COM void
pmcs_iqp_trace(pmcs_hw_t * pwp,uint32_t qnum)103710696SDavid.Hollister@Sun.COM pmcs_iqp_trace(pmcs_hw_t *pwp, uint32_t qnum)
103810696SDavid.Hollister@Sun.COM {
103911425SBing.Hu@Sun.COM 	uint32_t k = 0;
104011425SBing.Hu@Sun.COM 	int n = 0;
104110696SDavid.Hollister@Sun.COM 	uint32_t *ptr = NULL;
104210696SDavid.Hollister@Sun.COM 	char *tbuf = pwp->iqpt->curpos;
104310696SDavid.Hollister@Sun.COM 	uint32_t size_left = pwp->iqpt->size_left;
104410696SDavid.Hollister@Sun.COM 
104510696SDavid.Hollister@Sun.COM 	if (tbuf == NULL) {
104611048SDavid.Hollister@Sun.COM 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
104711048SDavid.Hollister@Sun.COM 		    "%s: trace buffer is not ready,"
104810696SDavid.Hollister@Sun.COM 		    " Inbound Message from host to SPC is not traced",
104910696SDavid.Hollister@Sun.COM 		    __func__);
105010696SDavid.Hollister@Sun.COM 		return;
105110696SDavid.Hollister@Sun.COM 	} else if (size_left < PMCS_QENTRY_SIZE * PMCS_QENTRY_SIZE) {
105210696SDavid.Hollister@Sun.COM 		tbuf = pwp->iqpt->curpos = pwp->iqpt->head;
105310696SDavid.Hollister@Sun.COM 		size_left = pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE;
105410696SDavid.Hollister@Sun.COM 	}
105510696SDavid.Hollister@Sun.COM 
105610696SDavid.Hollister@Sun.COM 	ptr = &pwp->iqp[qnum][pwp->shadow_iqpi[qnum] *
105710696SDavid.Hollister@Sun.COM 	    (PMCS_QENTRY_SIZE >> 2)];
105810696SDavid.Hollister@Sun.COM 	for (k = 0; k < (PMCS_QENTRY_SIZE / sizeof (uint32_t));
105910696SDavid.Hollister@Sun.COM 	    k += 8) {
106010696SDavid.Hollister@Sun.COM 		n += snprintf(&tbuf[n], (size_left - n),
106110696SDavid.Hollister@Sun.COM 		    "0x%08x 0x%08x 0x%08x 0x%08x "
106210696SDavid.Hollister@Sun.COM 		    "0x%08x 0x%08x 0x%08x 0x%08x\n",
106310696SDavid.Hollister@Sun.COM 		    LE_32(ptr[k]), LE_32(ptr[k+1]),
106410696SDavid.Hollister@Sun.COM 		    LE_32(ptr[k+2]), LE_32(ptr[k+3]),
106510696SDavid.Hollister@Sun.COM 		    LE_32(ptr[k+4]), LE_32(ptr[k+5]),
106610696SDavid.Hollister@Sun.COM 		    LE_32(ptr[k+6]), LE_32(ptr[k+7]));
106710696SDavid.Hollister@Sun.COM 	}
106810696SDavid.Hollister@Sun.COM 	pwp->iqpt->size_left -= n;
106910696SDavid.Hollister@Sun.COM 	if (pwp->iqpt->size_left > 0) {
107010696SDavid.Hollister@Sun.COM 		pwp->iqpt->curpos += n;
107110696SDavid.Hollister@Sun.COM 	} else {
107210696SDavid.Hollister@Sun.COM 		pwp->iqpt->curpos =
107310696SDavid.Hollister@Sun.COM 		    pwp->iqpt->head + PMCS_IQP_TRACE_BUFFER_SIZE - 1;
107410696SDavid.Hollister@Sun.COM 	}
107510696SDavid.Hollister@Sun.COM }
107610696SDavid.Hollister@Sun.COM 
107710696SDavid.Hollister@Sun.COM /*
107811425SBing.Hu@Sun.COM  * Capture HSST State Registers.
107911425SBing.Hu@Sun.COM  */
108011425SBing.Hu@Sun.COM static int
pmcs_dump_hsst_sregs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)108111425SBing.Hu@Sun.COM pmcs_dump_hsst_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
108211425SBing.Hu@Sun.COM {
108311425SBing.Hu@Sun.COM 	uint32_t i = 0, j = 0, addr = 0;
108411425SBing.Hu@Sun.COM 	int n = 0;
108511425SBing.Hu@Sun.COM 
108611425SBing.Hu@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nHSST State Capture : \n"
108711425SBing.Hu@Sun.COM 	    "-----------------\n");
108811425SBing.Hu@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "%s \t %s \n",
108911425SBing.Hu@Sun.COM 	    hsst_state[8].desc ? hsst_state[8].desc : "NULL",
109011425SBing.Hu@Sun.COM 	    hsst_state[16].desc ? hsst_state[16].desc : "NULL");
109111425SBing.Hu@Sun.COM 
109211425SBing.Hu@Sun.COM 	for (i = 0; i < 8; i++) {
109311425SBing.Hu@Sun.COM 		addr = hsst_state[i].offset_start +
109411425SBing.Hu@Sun.COM 		    hsst_state[i].shift_addr;
109511425SBing.Hu@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "Phy[%1d]\n", i);
109611425SBing.Hu@Sun.COM 		for (j = 0; j < 6; j++) {
109711425SBing.Hu@Sun.COM 			pmcs_wr_gsm_reg(pwp, addr, j);
109811425SBing.Hu@Sun.COM 			pmcs_wr_gsm_reg(pwp, addr, (0x0100 + j));
109911425SBing.Hu@Sun.COM 			addr = hsst_state[i+8].offset_start +
110011425SBing.Hu@Sun.COM 			    hsst_state[i+8].shift_addr;
110111425SBing.Hu@Sun.COM 			n += snprintf(&buf[n], (size_left - n),
110211980SDavid.Hollister@Sun.COM 			    "[%08X]: %08X\t", addr, pmcs_rd_gsm_reg(pwp, 0,
110311980SDavid.Hollister@Sun.COM 			    addr));
110411425SBing.Hu@Sun.COM 			addr = hsst_state[i+16].offset_start +
110511425SBing.Hu@Sun.COM 			    hsst_state[i+16].shift_addr;
110611425SBing.Hu@Sun.COM 			n += snprintf(&buf[n], (size_left - n),
110711980SDavid.Hollister@Sun.COM 			    "[%08X]: %08X\n", addr, pmcs_rd_gsm_reg(pwp, 0,
110811980SDavid.Hollister@Sun.COM 			    addr));
110911425SBing.Hu@Sun.COM 		}
111011425SBing.Hu@Sun.COM 
111111425SBing.Hu@Sun.COM 	}
111211425SBing.Hu@Sun.COM 	return (n);
111311425SBing.Hu@Sun.COM 
111411425SBing.Hu@Sun.COM }
111511425SBing.Hu@Sun.COM 
111611425SBing.Hu@Sun.COM /*
111711425SBing.Hu@Sun.COM  * Capture SSPA State Registers.
111811425SBing.Hu@Sun.COM  */
111911425SBing.Hu@Sun.COM static int
pmcs_dump_sspa_sregs(pmcs_hw_t * pwp,caddr_t buf,uint32_t size_left)112011425SBing.Hu@Sun.COM pmcs_dump_sspa_sregs(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left)
112111425SBing.Hu@Sun.COM {
112211425SBing.Hu@Sun.COM 	uint32_t i = 0, rv = 0, addr = 0;
112311425SBing.Hu@Sun.COM 	int n = 0;
112411425SBing.Hu@Sun.COM 
112511425SBing.Hu@Sun.COM 	n += snprintf(&buf[n], (size_left - n), "\nSSPA State Capture : \n"
112611425SBing.Hu@Sun.COM 	    "-----------------\n");
112711425SBing.Hu@Sun.COM 	for (i = 0; i < 8; i++) {
112811425SBing.Hu@Sun.COM 		if (sspa_state[i].flag & PMCS_SPREGS_BLOCK_START) {
112911425SBing.Hu@Sun.COM 			n += snprintf(&buf[n], (size_left - n), "%s \n",
113011425SBing.Hu@Sun.COM 			    sspa_state[i].desc ? sspa_state[i].desc : "NULL");
113111425SBing.Hu@Sun.COM 		}
113211425SBing.Hu@Sun.COM 		addr = sspa_state[i].offset_start + sspa_state[i].shift_addr;
113311980SDavid.Hollister@Sun.COM 		rv = pmcs_rd_gsm_reg(pwp, 0, addr);
113411425SBing.Hu@Sun.COM 		rv |= PMCS_SSPA_CONTROL_REGISTER_BIT27;
113511425SBing.Hu@Sun.COM 		pmcs_wr_gsm_reg(pwp, addr, rv);
113611425SBing.Hu@Sun.COM 		n += snprintf(&buf[n], (size_left - n), "[%08X]: %08X \n",
113711980SDavid.Hollister@Sun.COM 		    addr, pmcs_rd_gsm_reg(pwp, 0, addr));
113811425SBing.Hu@Sun.COM 
113911425SBing.Hu@Sun.COM 	}
114011425SBing.Hu@Sun.COM 	return (n);
114111425SBing.Hu@Sun.COM }
114211425SBing.Hu@Sun.COM 
114311425SBing.Hu@Sun.COM /*
114410696SDavid.Hollister@Sun.COM  * Dump fatal error register content from GSM.
114510696SDavid.Hollister@Sun.COM  */
114610696SDavid.Hollister@Sun.COM int
pmcs_dump_feregs(pmcs_hw_t * pwp,uint32_t * addr,uint8_t nvmd,caddr_t buf,uint32_t size_left)114710696SDavid.Hollister@Sun.COM pmcs_dump_feregs(pmcs_hw_t *pwp, uint32_t *addr, uint8_t nvmd,
114810696SDavid.Hollister@Sun.COM     caddr_t buf, uint32_t size_left)
114910696SDavid.Hollister@Sun.COM {
115010696SDavid.Hollister@Sun.COM 	uint32_t offset = 0, length = 0;
115110696SDavid.Hollister@Sun.COM 	int i = 0;
115210696SDavid.Hollister@Sun.COM 	uint8_t *ptr = (uint8_t *)addr;
115310696SDavid.Hollister@Sun.COM 
115410696SDavid.Hollister@Sun.COM 	if ((addr == NULL) || (buf == NULL)) {
115510696SDavid.Hollister@Sun.COM 		return (0);
115610696SDavid.Hollister@Sun.COM 	}
115710696SDavid.Hollister@Sun.COM 	switch (nvmd) {
115810696SDavid.Hollister@Sun.COM 		case PMCIN_NVMD_AAP1:
115910696SDavid.Hollister@Sun.COM 			offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOMSGU);
116010696SDavid.Hollister@Sun.COM 			length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLMSGU);
116110696SDavid.Hollister@Sun.COM 			break;
116210696SDavid.Hollister@Sun.COM 		case PMCIN_NVMD_IOP:
116310696SDavid.Hollister@Sun.COM 			offset = pmcs_rd_mpi_tbl(pwp, PMCS_FERDOIOP);
116410696SDavid.Hollister@Sun.COM 			length = pmcs_rd_mpi_tbl(pwp, PMCS_FERDLIOP);
116510696SDavid.Hollister@Sun.COM 			break;
116610696SDavid.Hollister@Sun.COM 		default:
116711048SDavid.Hollister@Sun.COM 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
116811048SDavid.Hollister@Sun.COM 			    "UNKNOWN NVMD DEVICE %s():%d", __func__, __LINE__);
116910696SDavid.Hollister@Sun.COM 			return (0);
117010696SDavid.Hollister@Sun.COM 	}
117110696SDavid.Hollister@Sun.COM 
117210696SDavid.Hollister@Sun.COM 	while ((i < length) && (ptr[i + offset] != 0xff) &&
117310696SDavid.Hollister@Sun.COM 	    (ptr[i + offset] != '\0')) {
117410696SDavid.Hollister@Sun.COM 		i += snprintf(&buf[i], (size_left - i),
117510696SDavid.Hollister@Sun.COM 		    "%c", ptr[i + offset]);
117610696SDavid.Hollister@Sun.COM 	}
117710696SDavid.Hollister@Sun.COM 	return (i);
117810696SDavid.Hollister@Sun.COM }
117911694SDavid.Hollister@Sun.COM 
118011694SDavid.Hollister@Sun.COM /*
118111694SDavid.Hollister@Sun.COM  * Write out either the AAP1 or IOP event log
118211694SDavid.Hollister@Sun.COM  */
118311694SDavid.Hollister@Sun.COM static void
pmcs_write_fwlog(pmcs_hw_t * pwp,pmcs_fw_event_hdr_t * fwlogp)118411694SDavid.Hollister@Sun.COM pmcs_write_fwlog(pmcs_hw_t *pwp, pmcs_fw_event_hdr_t *fwlogp)
118511694SDavid.Hollister@Sun.COM {
118611694SDavid.Hollister@Sun.COM 	struct vnode *vnp;
118711694SDavid.Hollister@Sun.COM 	caddr_t fwlogfile, bufp;
118811694SDavid.Hollister@Sun.COM 	rlim64_t rlimit;
118911694SDavid.Hollister@Sun.COM 	ssize_t resid;
119011694SDavid.Hollister@Sun.COM 	offset_t offset = 0;
119111694SDavid.Hollister@Sun.COM 	int error;
119211694SDavid.Hollister@Sun.COM 	uint32_t data_len;
119311694SDavid.Hollister@Sun.COM 
119411694SDavid.Hollister@Sun.COM 	if (fwlogp == pwp->fwlogp_aap1) {
119511694SDavid.Hollister@Sun.COM 		fwlogfile = pwp->fwlogfile_aap1;
119611694SDavid.Hollister@Sun.COM 	} else {
119711694SDavid.Hollister@Sun.COM 		fwlogfile = pwp->fwlogfile_iop;
119811694SDavid.Hollister@Sun.COM 	}
119911694SDavid.Hollister@Sun.COM 
120011694SDavid.Hollister@Sun.COM 	if ((error = vn_open(fwlogfile, UIO_SYSSPACE, FCREAT|FWRITE, 0644,
120111694SDavid.Hollister@Sun.COM 	    &vnp, CRCREAT, 0)) != 0) {
120211694SDavid.Hollister@Sun.COM 		pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
120311694SDavid.Hollister@Sun.COM 		    "%s: Could not create '%s', error %d", __func__,
120411694SDavid.Hollister@Sun.COM 		    fwlogfile, error);
120511694SDavid.Hollister@Sun.COM 		return;
120611694SDavid.Hollister@Sun.COM 	}
120711694SDavid.Hollister@Sun.COM 
120811694SDavid.Hollister@Sun.COM 	bufp = (caddr_t)fwlogp;
120911694SDavid.Hollister@Sun.COM 	data_len = PMCS_FWLOG_SIZE / 2;
121011694SDavid.Hollister@Sun.COM 	rlimit = data_len + 1;
121111694SDavid.Hollister@Sun.COM 	for (;;) {
121211694SDavid.Hollister@Sun.COM 		error = vn_rdwr(UIO_WRITE, vnp, bufp, data_len, offset,
121311694SDavid.Hollister@Sun.COM 		    UIO_SYSSPACE, FSYNC, rlimit, CRED(), &resid);
121411694SDavid.Hollister@Sun.COM 		if (error) {
121511694SDavid.Hollister@Sun.COM 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
121611694SDavid.Hollister@Sun.COM 			    "%s: could not write %s, error %d", __func__,
121711694SDavid.Hollister@Sun.COM 			    fwlogfile, error);
121811694SDavid.Hollister@Sun.COM 			break;
121911694SDavid.Hollister@Sun.COM 		}
122011694SDavid.Hollister@Sun.COM 		if (resid == data_len) {
122111694SDavid.Hollister@Sun.COM 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
122211694SDavid.Hollister@Sun.COM 			    "%s: Out of space in %s, error %d", __func__,
122311694SDavid.Hollister@Sun.COM 			    fwlogfile, error);
122411694SDavid.Hollister@Sun.COM 			error = ENOSPC;
122511694SDavid.Hollister@Sun.COM 			break;
122611694SDavid.Hollister@Sun.COM 		}
122711694SDavid.Hollister@Sun.COM 		if (resid == 0)
122811694SDavid.Hollister@Sun.COM 			break;
122911694SDavid.Hollister@Sun.COM 		offset += (data_len - resid);
123011694SDavid.Hollister@Sun.COM 		data_len = (ssize_t)resid;
123111694SDavid.Hollister@Sun.COM 	}
123211694SDavid.Hollister@Sun.COM 
123311694SDavid.Hollister@Sun.COM 	if (error = VOP_CLOSE(vnp, FWRITE, 1, (offset_t)0, kcred, NULL)) {
123411694SDavid.Hollister@Sun.COM 		if (!error) {
123511694SDavid.Hollister@Sun.COM 			pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
123611694SDavid.Hollister@Sun.COM 			    "%s: Error on close %s, error %d", __func__,
123711694SDavid.Hollister@Sun.COM 			    fwlogfile, error);
123811694SDavid.Hollister@Sun.COM 		}
123911694SDavid.Hollister@Sun.COM 	}
124011694SDavid.Hollister@Sun.COM 
124111694SDavid.Hollister@Sun.COM 	VN_RELE(vnp);
124211694SDavid.Hollister@Sun.COM }
124311694SDavid.Hollister@Sun.COM 
124411694SDavid.Hollister@Sun.COM /*
124511694SDavid.Hollister@Sun.COM  * Check the in-memory event log.  If it's filled up to or beyond the
124611694SDavid.Hollister@Sun.COM  * threshold, write it out to the configured filename.
124711694SDavid.Hollister@Sun.COM  */
124811694SDavid.Hollister@Sun.COM void
pmcs_gather_fwlog(pmcs_hw_t * pwp)124911694SDavid.Hollister@Sun.COM pmcs_gather_fwlog(pmcs_hw_t *pwp)
125011694SDavid.Hollister@Sun.COM {
125111694SDavid.Hollister@Sun.COM 	uint32_t num_entries_aap1, num_entries_iop, fname_suffix;
125211694SDavid.Hollister@Sun.COM 
125311694SDavid.Hollister@Sun.COM 	ASSERT(!mutex_owned(&pwp->lock));
125411694SDavid.Hollister@Sun.COM 
125511694SDavid.Hollister@Sun.COM 	/*
125611694SDavid.Hollister@Sun.COM 	 * Get our copies of the latest indices
125711694SDavid.Hollister@Sun.COM 	 */
125811694SDavid.Hollister@Sun.COM 	pwp->fwlog_latest_idx_aap1 = pwp->fwlogp_aap1->fw_el_latest_idx;
125911694SDavid.Hollister@Sun.COM 	pwp->fwlog_latest_idx_iop = pwp->fwlogp_iop->fw_el_latest_idx;
126011694SDavid.Hollister@Sun.COM 
126111694SDavid.Hollister@Sun.COM 	/*
126211694SDavid.Hollister@Sun.COM 	 * We need entries in the log before we can know how big they are
126311694SDavid.Hollister@Sun.COM 	 */
126411694SDavid.Hollister@Sun.COM 	if ((pwp->fwlog_max_entries_aap1 == 0) &&
126511694SDavid.Hollister@Sun.COM 	    (pwp->fwlogp_aap1->fw_el_latest_idx != 0)) {
126611694SDavid.Hollister@Sun.COM 		pwp->fwlog_max_entries_aap1 =
126711694SDavid.Hollister@Sun.COM 		    (PMCS_FWLOG_SIZE / 2) / pwp->fwlogp_aap1->fw_el_entry_size;
126811694SDavid.Hollister@Sun.COM 		pwp->fwlog_threshold_aap1 =
126911694SDavid.Hollister@Sun.COM 		    (pwp->fwlog_max_entries_aap1 * PMCS_FWLOG_THRESH) / 100;
127011694SDavid.Hollister@Sun.COM 	}
127111694SDavid.Hollister@Sun.COM 
127211694SDavid.Hollister@Sun.COM 	if ((pwp->fwlog_max_entries_iop == 0) &&
127311694SDavid.Hollister@Sun.COM 	    (pwp->fwlogp_iop->fw_el_latest_idx != 0)) {
127411694SDavid.Hollister@Sun.COM 		pwp->fwlog_max_entries_iop =
127511694SDavid.Hollister@Sun.COM 		    (PMCS_FWLOG_SIZE / 2) / pwp->fwlogp_iop->fw_el_entry_size;
127611694SDavid.Hollister@Sun.COM 		pwp->fwlog_threshold_iop =
127711694SDavid.Hollister@Sun.COM 		    (pwp->fwlog_max_entries_iop * PMCS_FWLOG_THRESH) / 100;
127811694SDavid.Hollister@Sun.COM 	}
127911694SDavid.Hollister@Sun.COM 
128011694SDavid.Hollister@Sun.COM 	/*
128111694SDavid.Hollister@Sun.COM 	 * Check if we've reached the threshold in the AAP1 log.  We do this
128211694SDavid.Hollister@Sun.COM 	 * by comparing the latest index with our copy of the oldest index
128311694SDavid.Hollister@Sun.COM 	 * (not the chip's).
128411694SDavid.Hollister@Sun.COM 	 */
128511694SDavid.Hollister@Sun.COM 	if (pwp->fwlog_latest_idx_aap1 >= pwp->fwlog_oldest_idx_aap1) {
128611694SDavid.Hollister@Sun.COM 		/* Log has not wrapped */
128711694SDavid.Hollister@Sun.COM 		num_entries_aap1 =
128811694SDavid.Hollister@Sun.COM 		    pwp->fwlog_latest_idx_aap1 - pwp->fwlog_oldest_idx_aap1;
128911694SDavid.Hollister@Sun.COM 	} else {
129011694SDavid.Hollister@Sun.COM 		/* Log has wrapped */
129111694SDavid.Hollister@Sun.COM 		num_entries_aap1 = pwp->fwlog_max_entries_aap1 -
129211694SDavid.Hollister@Sun.COM 		    (pwp->fwlog_oldest_idx_aap1 - pwp->fwlog_latest_idx_aap1);
129311694SDavid.Hollister@Sun.COM 	}
129411694SDavid.Hollister@Sun.COM 
129511694SDavid.Hollister@Sun.COM 	/*
129611694SDavid.Hollister@Sun.COM 	 * Now check the IOP log
129711694SDavid.Hollister@Sun.COM 	 */
129811694SDavid.Hollister@Sun.COM 	if (pwp->fwlog_latest_idx_iop >= pwp->fwlog_oldest_idx_iop) {
129911694SDavid.Hollister@Sun.COM 		/* Log has not wrapped */
130011694SDavid.Hollister@Sun.COM 		num_entries_iop = pwp->fwlog_latest_idx_iop -
130111694SDavid.Hollister@Sun.COM 		    pwp->fwlog_oldest_idx_iop;
130211694SDavid.Hollister@Sun.COM 	} else {
130311694SDavid.Hollister@Sun.COM 		/* Log has wrapped */
130411694SDavid.Hollister@Sun.COM 		num_entries_iop = pwp->fwlog_max_entries_iop -
130511694SDavid.Hollister@Sun.COM 		    (pwp->fwlog_oldest_idx_iop - pwp->fwlog_latest_idx_iop);
130611694SDavid.Hollister@Sun.COM 	}
130711694SDavid.Hollister@Sun.COM 
130811694SDavid.Hollister@Sun.COM 	if ((num_entries_aap1 < pwp->fwlog_threshold_aap1) &&
130911694SDavid.Hollister@Sun.COM 	    (num_entries_iop < pwp->fwlog_threshold_iop)) {
131011694SDavid.Hollister@Sun.COM 		return;
131111694SDavid.Hollister@Sun.COM 	}
131211694SDavid.Hollister@Sun.COM 
131311694SDavid.Hollister@Sun.COM 	/*
131411926SDavid.Hollister@Sun.COM 	 * We also can't write the event log out if it's too early in boot
131511926SDavid.Hollister@Sun.COM 	 * (i.e. the root fs isn't mounted yet).
131611926SDavid.Hollister@Sun.COM 	 */
131711926SDavid.Hollister@Sun.COM 	if (!modrootloaded) {
131811926SDavid.Hollister@Sun.COM 		return;
131911926SDavid.Hollister@Sun.COM 	}
132011926SDavid.Hollister@Sun.COM 
132111926SDavid.Hollister@Sun.COM 	/*
132211694SDavid.Hollister@Sun.COM 	 * Write out the necessary log file(s), update the "oldest" pointers
132311694SDavid.Hollister@Sun.COM 	 * and the suffix to the written filenames.
132411694SDavid.Hollister@Sun.COM 	 */
132511694SDavid.Hollister@Sun.COM 	if (num_entries_aap1 >= pwp->fwlog_threshold_aap1) {
132611694SDavid.Hollister@Sun.COM 		pmcs_write_fwlog(pwp, pwp->fwlogp_aap1);
132711694SDavid.Hollister@Sun.COM 		pwp->fwlog_oldest_idx_aap1 = pwp->fwlog_latest_idx_aap1;
132811694SDavid.Hollister@Sun.COM 
132911694SDavid.Hollister@Sun.COM 		fname_suffix = strlen(pwp->fwlogfile_aap1) - 1;
133011694SDavid.Hollister@Sun.COM 		if (pwp->fwlogfile_aap1[fname_suffix] == '4') {
133111694SDavid.Hollister@Sun.COM 			pwp->fwlogfile_aap1[fname_suffix] = '0';
133211694SDavid.Hollister@Sun.COM 		} else {
133311694SDavid.Hollister@Sun.COM 			++pwp->fwlogfile_aap1[fname_suffix];
133411694SDavid.Hollister@Sun.COM 		}
133511694SDavid.Hollister@Sun.COM 	}
133611694SDavid.Hollister@Sun.COM 
133711694SDavid.Hollister@Sun.COM 	if (num_entries_iop >= pwp->fwlog_threshold_iop) {
133811694SDavid.Hollister@Sun.COM 		pmcs_write_fwlog(pwp, pwp->fwlogp_iop);
133911694SDavid.Hollister@Sun.COM 		pwp->fwlog_oldest_idx_iop = pwp->fwlog_latest_idx_iop;
134011694SDavid.Hollister@Sun.COM 
134111694SDavid.Hollister@Sun.COM 		fname_suffix = strlen(pwp->fwlogfile_iop) - 1;
134211694SDavid.Hollister@Sun.COM 		if (pwp->fwlogfile_iop[fname_suffix] == '4') {
134311694SDavid.Hollister@Sun.COM 			pwp->fwlogfile_iop[fname_suffix] = '0';
134411694SDavid.Hollister@Sun.COM 		} else {
134511694SDavid.Hollister@Sun.COM 			++pwp->fwlogfile_iop[fname_suffix];
134611694SDavid.Hollister@Sun.COM 		}
134711694SDavid.Hollister@Sun.COM 	}
134811694SDavid.Hollister@Sun.COM }
1349