xref: /titanic_44/usr/src/uts/sun4u/io/pci/pcipsy.c (revision 394707299ee511c373a7a164a534980fb01d39d0)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5a1ca9cb8Sarutz  * Common Development and Distribution License (the "License").
6a1ca9cb8Sarutz  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*39470729Skd93003  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * Psycho+ specifics implementation:
307c478bd9Sstevel@tonic-gate  *	interrupt mapping register
317c478bd9Sstevel@tonic-gate  *	PBM configuration
327c478bd9Sstevel@tonic-gate  *	ECC and PBM error handling
337c478bd9Sstevel@tonic-gate  *	Iommu mapping handling
347c478bd9Sstevel@tonic-gate  *	Streaming Cache flushing
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
397c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
407c478bd9Sstevel@tonic-gate #include <sys/async.h>
417c478bd9Sstevel@tonic-gate #include <sys/systm.h>
427c478bd9Sstevel@tonic-gate #include <sys/intreg.h>		/* UPAID_TO_IGN() */
43b0fc0e77Sgovinda #include <sys/ivintr.h>
447c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
457c478bd9Sstevel@tonic-gate #include <sys/sunndi.h>
467c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
477c478bd9Sstevel@tonic-gate #include <sys/fm/util.h>
487c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
497c478bd9Sstevel@tonic-gate #include <sys/iommutsb.h>
507c478bd9Sstevel@tonic-gate #include <sys/spl.h>
517c478bd9Sstevel@tonic-gate #include <sys/fm/util.h>
527c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h>
537c478bd9Sstevel@tonic-gate #include <sys/fm/io/pci.h>
547c478bd9Sstevel@tonic-gate #include <sys/fm/io/sun4upci.h>
557c478bd9Sstevel@tonic-gate #include <sys/pci/pci_obj.h>
567c478bd9Sstevel@tonic-gate #include <sys/pci/pcipsy.h>
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #ifdef _STARFIRE
597c478bd9Sstevel@tonic-gate #include <sys/starfire.h>
607c478bd9Sstevel@tonic-gate #endif /* _STARFIRE */
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate static uint32_t pci_identity_init(pci_t *pci_p);
637c478bd9Sstevel@tonic-gate static int pci_intr_setup(pci_t *pci_p);
647c478bd9Sstevel@tonic-gate static void pci_pbm_errstate_get(pci_t *pci_p, pbm_errstate_t *pbm_err_p);
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate static pci_ksinfo_t	*pci_name_kstat;
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
697c478bd9Sstevel@tonic-gate /* called by pci_attach() DDI_ATTACH to initialize pci objects */
707c478bd9Sstevel@tonic-gate int
pci_obj_setup(pci_t * pci_p)717c478bd9Sstevel@tonic-gate pci_obj_setup(pci_t *pci_p)
727c478bd9Sstevel@tonic-gate {
737c478bd9Sstevel@tonic-gate 	pci_common_t *cmn_p;
747c478bd9Sstevel@tonic-gate 	int ret;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate 	mutex_enter(&pci_global_mutex);
777c478bd9Sstevel@tonic-gate 	cmn_p = get_pci_common_soft_state(pci_p->pci_id);
787c478bd9Sstevel@tonic-gate 	if (cmn_p == NULL) {
797c478bd9Sstevel@tonic-gate 		uint_t id = pci_p->pci_id;
807c478bd9Sstevel@tonic-gate 		if (alloc_pci_common_soft_state(id) != DDI_SUCCESS) {
817c478bd9Sstevel@tonic-gate 			mutex_exit(&pci_global_mutex);
827c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
837c478bd9Sstevel@tonic-gate 		}
847c478bd9Sstevel@tonic-gate 		cmn_p = get_pci_common_soft_state(id);
857c478bd9Sstevel@tonic-gate 		cmn_p->pci_common_id = id;
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	ASSERT((pci_p->pci_side == 0) || (pci_p->pci_side == 1));
897c478bd9Sstevel@tonic-gate 	if (cmn_p->pci_p[pci_p->pci_side]) {
907c478bd9Sstevel@tonic-gate 		/* second side attach */
917c478bd9Sstevel@tonic-gate 		pci_p->pci_side = PCI_OTHER_SIDE(pci_p->pci_side);
927c478bd9Sstevel@tonic-gate 		ASSERT(cmn_p->pci_p[pci_p->pci_side] == NULL);
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	cmn_p->pci_p[pci_p->pci_side] = pci_p;
967c478bd9Sstevel@tonic-gate 	pci_p->pci_common_p = cmn_p;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	if (cmn_p->pci_common_refcnt == 0) {
997c478bd9Sstevel@tonic-gate 		/* Perform allocation first to avoid delicate unwinding. */
1007c478bd9Sstevel@tonic-gate 		if (pci_alloc_tsb(pci_p) != DDI_SUCCESS) {
1017c478bd9Sstevel@tonic-gate 			cmn_p->pci_p[pci_p->pci_side] = NULL;
1027c478bd9Sstevel@tonic-gate 			pci_p->pci_common_p = NULL;
1037c478bd9Sstevel@tonic-gate 			free_pci_common_soft_state(cmn_p->pci_common_id);
1047c478bd9Sstevel@tonic-gate 			mutex_exit(&pci_global_mutex);
1057c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
1067c478bd9Sstevel@tonic-gate 		}
1077c478bd9Sstevel@tonic-gate 		cmn_p->pci_common_tsb_cookie = pci_p->pci_tsb_cookie;
1087c478bd9Sstevel@tonic-gate 		cmn_p->pci_chip_id = pci_identity_init(pci_p);
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 		ib_create(pci_p);
1117c478bd9Sstevel@tonic-gate 		cmn_p->pci_common_ib_p = pci_p->pci_ib_p;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		cb_create(pci_p);
1147c478bd9Sstevel@tonic-gate 		cmn_p->pci_common_cb_p = pci_p->pci_cb_p;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 		iommu_create(pci_p);
1177c478bd9Sstevel@tonic-gate 		cmn_p->pci_common_iommu_p = pci_p->pci_iommu_p;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 		ecc_create(pci_p);
1207c478bd9Sstevel@tonic-gate 		cmn_p->pci_common_ecc_p = pci_p->pci_ecc_p;
1217c478bd9Sstevel@tonic-gate 	} else {
1227c478bd9Sstevel@tonic-gate 		ASSERT(cmn_p->pci_common_refcnt == 1);
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 		pci_p->pci_tsb_cookie = cmn_p->pci_common_tsb_cookie;
1257c478bd9Sstevel@tonic-gate 		pci_p->pci_ib_p = cmn_p->pci_common_ib_p;
1267c478bd9Sstevel@tonic-gate 		pci_p->pci_cb_p = cmn_p->pci_common_cb_p;
1277c478bd9Sstevel@tonic-gate 		pci_p->pci_iommu_p = cmn_p->pci_common_iommu_p;
1287c478bd9Sstevel@tonic-gate 		pci_p->pci_ecc_p = cmn_p->pci_common_ecc_p;
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	pbm_create(pci_p);
1327c478bd9Sstevel@tonic-gate 	sc_create(pci_p);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	pci_fm_create(pci_p);
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if ((ret = pci_intr_setup(pci_p)) != DDI_SUCCESS)
1377c478bd9Sstevel@tonic-gate 		goto done;
1387c478bd9Sstevel@tonic-gate 	if (CHIP_TYPE(pci_p) == PCI_CHIP_PSYCHO)
1397c478bd9Sstevel@tonic-gate 		pci_kstat_create(pci_p);
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	cmn_p->pci_common_attachcnt++;
1427c478bd9Sstevel@tonic-gate 	cmn_p->pci_common_refcnt++;
1437c478bd9Sstevel@tonic-gate done:
1447c478bd9Sstevel@tonic-gate 	mutex_exit(&pci_global_mutex);
1457c478bd9Sstevel@tonic-gate 	if (ret != DDI_SUCCESS)
1467c478bd9Sstevel@tonic-gate 		cmn_err(CE_NOTE, "Interrupt register failure, returning 0x%x\n",
1477c478bd9Sstevel@tonic-gate 			ret);
1487c478bd9Sstevel@tonic-gate 	return (ret);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /* called by pci_detach() DDI_DETACH to destroy pci objects */
1527c478bd9Sstevel@tonic-gate void
pci_obj_destroy(pci_t * pci_p)1537c478bd9Sstevel@tonic-gate pci_obj_destroy(pci_t *pci_p)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	pci_common_t *cmn_p;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	mutex_enter(&pci_global_mutex);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	cmn_p = pci_p->pci_common_p;
1607c478bd9Sstevel@tonic-gate 	cmn_p->pci_common_refcnt--;
1617c478bd9Sstevel@tonic-gate 	cmn_p->pci_common_attachcnt--;
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	pci_kstat_destroy(pci_p);
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	sc_destroy(pci_p);
1667c478bd9Sstevel@tonic-gate 	pbm_destroy(pci_p);
1677c478bd9Sstevel@tonic-gate 	pci_fm_destroy(pci_p);
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	if (cmn_p->pci_common_refcnt != 0) {
1707c478bd9Sstevel@tonic-gate 		cmn_p->pci_p[pci_p->pci_side] = NULL;
1717c478bd9Sstevel@tonic-gate 		mutex_exit(&pci_global_mutex);
1727c478bd9Sstevel@tonic-gate 		return;
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	ecc_destroy(pci_p);
1767c478bd9Sstevel@tonic-gate 	iommu_destroy(pci_p);
1777c478bd9Sstevel@tonic-gate 	cb_destroy(pci_p);
1787c478bd9Sstevel@tonic-gate 	ib_destroy(pci_p);
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	free_pci_common_soft_state(cmn_p->pci_common_id);
1817c478bd9Sstevel@tonic-gate 	pci_intr_teardown(pci_p);
1827c478bd9Sstevel@tonic-gate 	mutex_exit(&pci_global_mutex);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /* called by pci_attach() DDI_RESUME to (re)initialize pci objects */
1867c478bd9Sstevel@tonic-gate void
pci_obj_resume(pci_t * pci_p)1877c478bd9Sstevel@tonic-gate pci_obj_resume(pci_t *pci_p)
1887c478bd9Sstevel@tonic-gate {
1897c478bd9Sstevel@tonic-gate 	pci_common_t *cmn_p = pci_p->pci_common_p;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	mutex_enter(&pci_global_mutex);
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	if (cmn_p->pci_common_attachcnt == 0) {
1947c478bd9Sstevel@tonic-gate 		ib_configure(pci_p->pci_ib_p);
1957c478bd9Sstevel@tonic-gate 		iommu_configure(pci_p->pci_iommu_p);
1967c478bd9Sstevel@tonic-gate 		ecc_configure(pci_p);
1977c478bd9Sstevel@tonic-gate 		ib_resume(pci_p->pci_ib_p);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	pbm_configure(pci_p->pci_pbm_p);
2017c478bd9Sstevel@tonic-gate 	sc_configure(pci_p->pci_sc_p);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	if (cmn_p->pci_common_attachcnt == 0)
2047c478bd9Sstevel@tonic-gate 		cb_resume(pci_p->pci_cb_p);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	pbm_resume(pci_p->pci_pbm_p);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	cmn_p->pci_common_attachcnt++;
2097c478bd9Sstevel@tonic-gate 	mutex_exit(&pci_global_mutex);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate /* called by pci_detach() DDI_SUSPEND to suspend pci objects */
2137c478bd9Sstevel@tonic-gate void
pci_obj_suspend(pci_t * pci_p)2147c478bd9Sstevel@tonic-gate pci_obj_suspend(pci_t *pci_p)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate 	mutex_enter(&pci_global_mutex);
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	pbm_suspend(pci_p->pci_pbm_p);
2197c478bd9Sstevel@tonic-gate 	if (!--pci_p->pci_common_p->pci_common_attachcnt) {
2207c478bd9Sstevel@tonic-gate 		ib_suspend(pci_p->pci_ib_p);
2217c478bd9Sstevel@tonic-gate 		cb_suspend(pci_p->pci_cb_p);
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	mutex_exit(&pci_global_mutex);
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate static uint32_t javelin_prom_fix[] = {0xfff800, 0, 0, 0x3f};
2287c478bd9Sstevel@tonic-gate static int
pci_intr_setup(pci_t * pci_p)2297c478bd9Sstevel@tonic-gate pci_intr_setup(pci_t *pci_p)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	extern char *platform;
2327c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pci_p->pci_dip;
2337c478bd9Sstevel@tonic-gate 	pbm_t *pbm_p = pci_p->pci_pbm_p;
2347c478bd9Sstevel@tonic-gate 	cb_t *cb_p = pci_p->pci_cb_p;
2357c478bd9Sstevel@tonic-gate 	int i, no_of_intrs;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/*
2387c478bd9Sstevel@tonic-gate 	 * This is a hack to fix a broken imap entry in the javelin PROM.
2397c478bd9Sstevel@tonic-gate 	 * see bugid 4226603
2407c478bd9Sstevel@tonic-gate 	 */
2417c478bd9Sstevel@tonic-gate 	if (strcmp((const char *)&platform, "SUNW,Ultra-250") == 0)
2427c478bd9Sstevel@tonic-gate 		(void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
2437c478bd9Sstevel@tonic-gate 		    "interrupt-map-mask", (caddr_t)javelin_prom_fix,
2447c478bd9Sstevel@tonic-gate 		    sizeof (javelin_prom_fix));
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	/*
2477c478bd9Sstevel@tonic-gate 	 * Get the interrupts property.
2487c478bd9Sstevel@tonic-gate 	 */
249a3282898Scth 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2507c478bd9Sstevel@tonic-gate 		"interrupts", (caddr_t)&pci_p->pci_inos,
2517c478bd9Sstevel@tonic-gate 		&pci_p->pci_inos_len) != DDI_SUCCESS)
2527c478bd9Sstevel@tonic-gate 		cmn_err(CE_PANIC, "%s%d: no interrupts property\n",
2537c478bd9Sstevel@tonic-gate 			ddi_driver_name(dip), ddi_get_instance(dip));
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/*
2567c478bd9Sstevel@tonic-gate 	 * figure out number of interrupts in the "interrupts" property
2577c478bd9Sstevel@tonic-gate 	 * and convert them all into ino.
2587c478bd9Sstevel@tonic-gate 	 */
2597c478bd9Sstevel@tonic-gate 	i = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "#interrupt-cells", 1);
2607c478bd9Sstevel@tonic-gate 	i = CELLS_1275_TO_BYTES(i);
2617c478bd9Sstevel@tonic-gate 	no_of_intrs = pci_p->pci_inos_len / i;
2627c478bd9Sstevel@tonic-gate 	for (i = 0; i < no_of_intrs; i++)
2637c478bd9Sstevel@tonic-gate 		pci_p->pci_inos[i] = IB_MONDO_TO_INO(pci_p->pci_inos[i]);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	if (pci_p->pci_common_p->pci_common_refcnt == 0) {
2667c478bd9Sstevel@tonic-gate 		cb_p->cb_no_of_inos = no_of_intrs;
2677c478bd9Sstevel@tonic-gate 		if (i = cb_register_intr(pci_p))
2687c478bd9Sstevel@tonic-gate 			goto teardown;
2697c478bd9Sstevel@tonic-gate 		if (i = ecc_register_intr(pci_p))
2707c478bd9Sstevel@tonic-gate 			goto teardown;
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 		intr_dist_add(cb_intr_dist, cb_p);
2737c478bd9Sstevel@tonic-gate 		cb_enable_intr(pci_p);
2747c478bd9Sstevel@tonic-gate 		ecc_enable_intr(pci_p);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	if (i = pbm_register_intr(pbm_p)) {
2787c478bd9Sstevel@tonic-gate 		if (pci_p->pci_common_p->pci_common_refcnt == 0)
2797c478bd9Sstevel@tonic-gate 			intr_dist_rem(cb_intr_dist, cb_p);
2807c478bd9Sstevel@tonic-gate 		goto teardown;
2817c478bd9Sstevel@tonic-gate 	}
2827c478bd9Sstevel@tonic-gate 	intr_dist_add(pbm_intr_dist, pbm_p);
2837c478bd9Sstevel@tonic-gate 	ib_intr_enable(pci_p, pci_p->pci_inos[CBNINTR_PBM]);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	if (pci_p->pci_common_p->pci_common_refcnt == 0)
2867c478bd9Sstevel@tonic-gate 		intr_dist_add_weighted(ib_intr_dist_all, pci_p->pci_ib_p);
2877c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2887c478bd9Sstevel@tonic-gate teardown:
2897c478bd9Sstevel@tonic-gate 	pci_intr_teardown(pci_p);
2907c478bd9Sstevel@tonic-gate 	return (i);
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate  * pci_fix_ranges - fixes the config space entry of the "ranges"
2957c478bd9Sstevel@tonic-gate  *	property on psycho+ platforms
2967c478bd9Sstevel@tonic-gate  */
2977c478bd9Sstevel@tonic-gate void
pci_fix_ranges(pci_ranges_t * rng_p,int rng_entries)2987c478bd9Sstevel@tonic-gate pci_fix_ranges(pci_ranges_t *rng_p, int rng_entries)
2997c478bd9Sstevel@tonic-gate {
3007c478bd9Sstevel@tonic-gate 	int i;
3017c478bd9Sstevel@tonic-gate 	for (i = 0; i < rng_entries; i++, rng_p++)
3027c478bd9Sstevel@tonic-gate 		if ((rng_p->child_high & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG)
3037c478bd9Sstevel@tonic-gate 			rng_p->parent_low |= rng_p->child_high;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate /*
3077c478bd9Sstevel@tonic-gate  * map_pci_registers
3087c478bd9Sstevel@tonic-gate  *
3097c478bd9Sstevel@tonic-gate  * This function is called from the attach routine to map the registers
3107c478bd9Sstevel@tonic-gate  * accessed by this driver.
3117c478bd9Sstevel@tonic-gate  *
3127c478bd9Sstevel@tonic-gate  * used by: pci_attach()
3137c478bd9Sstevel@tonic-gate  *
3147c478bd9Sstevel@tonic-gate  * return value: DDI_FAILURE on failure
3157c478bd9Sstevel@tonic-gate  */
3167c478bd9Sstevel@tonic-gate int
map_pci_registers(pci_t * pci_p,dev_info_t * dip)3177c478bd9Sstevel@tonic-gate map_pci_registers(pci_t *pci_p, dev_info_t *dip)
3187c478bd9Sstevel@tonic-gate {
3197c478bd9Sstevel@tonic-gate 	ddi_device_acc_attr_t attr;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3227c478bd9Sstevel@tonic-gate 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
3257c478bd9Sstevel@tonic-gate 	if (ddi_regs_map_setup(dip, 0, &pci_p->pci_address[0], 0, 0,
3267c478bd9Sstevel@tonic-gate 	    &attr, &pci_p->pci_ac[0]) != DDI_SUCCESS) {
3277c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s%d: unable to map reg entry 0\n",
3287c478bd9Sstevel@tonic-gate 			ddi_driver_name(dip), ddi_get_instance(dip));
3297c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 	/*
3327c478bd9Sstevel@tonic-gate 	 * if we don't have streaming buffer, then we don't have
3337c478bd9Sstevel@tonic-gate 	 * pci_address[2].
3347c478bd9Sstevel@tonic-gate 	 */
3357c478bd9Sstevel@tonic-gate 	if (pci_stream_buf_exists &&
3367c478bd9Sstevel@tonic-gate 	    ddi_regs_map_setup(dip, 2, &pci_p->pci_address[2], 0, 0,
3377c478bd9Sstevel@tonic-gate 	    &attr, &pci_p->pci_ac[2]) != DDI_SUCCESS) {
3387c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s%d: unable to map reg entry 2\n",
3397c478bd9Sstevel@tonic-gate 			ddi_driver_name(dip), ddi_get_instance(dip));
3407c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&pci_p->pci_ac[0]);
3417c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3427c478bd9Sstevel@tonic-gate 	}
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	/*
3457c478bd9Sstevel@tonic-gate 	 * The second register set contains the bridge's configuration
3467c478bd9Sstevel@tonic-gate 	 * header.  This header is at the very beginning of the bridge's
3477c478bd9Sstevel@tonic-gate 	 * configuration space.  This space has litte-endian byte order.
3487c478bd9Sstevel@tonic-gate 	 */
3497c478bd9Sstevel@tonic-gate 	attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
3507c478bd9Sstevel@tonic-gate 	if (ddi_regs_map_setup(dip, 1, &pci_p->pci_address[1], 0,
3517c478bd9Sstevel@tonic-gate 	    PCI_CONF_HDR_SIZE, &attr, &pci_p->pci_ac[1]) != DDI_SUCCESS) {
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s%d: unable to map reg entry 1\n",
3547c478bd9Sstevel@tonic-gate 			ddi_driver_name(dip), ddi_get_instance(dip));
3557c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&pci_p->pci_ac[0]);
3567c478bd9Sstevel@tonic-gate 		if (pci_stream_buf_exists)
3577c478bd9Sstevel@tonic-gate 			ddi_regs_map_free(&pci_p->pci_ac[2]);
3587c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 	DEBUG3(DBG_ATTACH, dip, "address (%p,%p,%p)\n",
3617c478bd9Sstevel@tonic-gate 	    pci_p->pci_address[0], pci_p->pci_address[1],
3627c478bd9Sstevel@tonic-gate 	    pci_p->pci_address[2]);
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate  * unmap_pci_registers:
3697c478bd9Sstevel@tonic-gate  *
3707c478bd9Sstevel@tonic-gate  * This routine unmap the registers mapped by map_pci_registers.
3717c478bd9Sstevel@tonic-gate  *
3727c478bd9Sstevel@tonic-gate  * used by: pci_detach()
3737c478bd9Sstevel@tonic-gate  *
3747c478bd9Sstevel@tonic-gate  * return value: none
3757c478bd9Sstevel@tonic-gate  */
3767c478bd9Sstevel@tonic-gate void
unmap_pci_registers(pci_t * pci_p)3777c478bd9Sstevel@tonic-gate unmap_pci_registers(pci_t *pci_p)
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&pci_p->pci_ac[0]);
3807c478bd9Sstevel@tonic-gate 	ddi_regs_map_free(&pci_p->pci_ac[1]);
3817c478bd9Sstevel@tonic-gate 	if (pci_stream_buf_exists)
3827c478bd9Sstevel@tonic-gate 		ddi_regs_map_free(&pci_p->pci_ac[2]);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate  * These convenience wrappers relies on map_pci_registers() to setup
3877c478bd9Sstevel@tonic-gate  * pci_address[0-2] correctly at first.
3887c478bd9Sstevel@tonic-gate  */
3897c478bd9Sstevel@tonic-gate /* The psycho+ reg base is at 1fe.0000.0000 */
3907c478bd9Sstevel@tonic-gate static uintptr_t
get_reg_base(pci_t * pci_p)3917c478bd9Sstevel@tonic-gate get_reg_base(pci_t *pci_p)
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	return ((uintptr_t)pci_p->pci_address[pci_stream_buf_exists ? 2 : 0]);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate /* The psycho+ config reg base is always the 2nd reg entry */
3977c478bd9Sstevel@tonic-gate static uintptr_t
get_config_reg_base(pci_t * pci_p)3987c478bd9Sstevel@tonic-gate get_config_reg_base(pci_t *pci_p)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate 	return ((uintptr_t)(pci_p->pci_address[1]));
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate uint64_t
ib_get_map_reg(ib_mondo_t mondo,uint32_t cpu_id)4047c478bd9Sstevel@tonic-gate ib_get_map_reg(ib_mondo_t mondo, uint32_t cpu_id)
4057c478bd9Sstevel@tonic-gate {
4067c478bd9Sstevel@tonic-gate 	return ((mondo) | (cpu_id << COMMON_INTR_MAP_REG_TID_SHIFT) |
4077c478bd9Sstevel@tonic-gate 	    COMMON_INTR_MAP_REG_VALID);
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate uint32_t
ib_map_reg_get_cpu(volatile uint64_t reg)4127c478bd9Sstevel@tonic-gate ib_map_reg_get_cpu(volatile uint64_t reg)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	return ((reg & COMMON_INTR_MAP_REG_TID) >>
4157c478bd9Sstevel@tonic-gate 	    COMMON_INTR_MAP_REG_TID_SHIFT);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate uint64_t *
ib_intr_map_reg_addr(ib_t * ib_p,ib_ino_t ino)4197c478bd9Sstevel@tonic-gate ib_intr_map_reg_addr(ib_t *ib_p, ib_ino_t ino)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	uint64_t *addr;
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	if (ino & 0x20)
4247c478bd9Sstevel@tonic-gate 		addr = (uint64_t *)(ib_p->ib_obio_intr_map_regs +
4257c478bd9Sstevel@tonic-gate 		    (((uint_t)ino & 0x1f) << 3));
4267c478bd9Sstevel@tonic-gate 	else
4277c478bd9Sstevel@tonic-gate 		addr = (uint64_t *)(ib_p->ib_slot_intr_map_regs +
4287c478bd9Sstevel@tonic-gate 		    (((uint_t)ino & 0x3c) << 1));
4297c478bd9Sstevel@tonic-gate 	return (addr);
4307c478bd9Sstevel@tonic-gate }
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate uint64_t *
ib_clear_intr_reg_addr(ib_t * ib_p,ib_ino_t ino)4337c478bd9Sstevel@tonic-gate ib_clear_intr_reg_addr(ib_t *ib_p, ib_ino_t ino)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	uint64_t *addr;
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	if (ino & 0x20)
4387c478bd9Sstevel@tonic-gate 		addr = (uint64_t *)(ib_p->ib_obio_clear_intr_regs +
4397c478bd9Sstevel@tonic-gate 		    (((uint_t)ino & 0x1f) << 3));
4407c478bd9Sstevel@tonic-gate 	else
4417c478bd9Sstevel@tonic-gate 		addr = (uint64_t *)(ib_p->ib_slot_clear_intr_regs +
4427c478bd9Sstevel@tonic-gate 		    (((uint_t)ino & 0x1f) << 3));
4437c478bd9Sstevel@tonic-gate 	return (addr);
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate  * psycho have one mapping register per slot
4487c478bd9Sstevel@tonic-gate  */
4497c478bd9Sstevel@tonic-gate void
ib_ino_map_reg_share(ib_t * ib_p,ib_ino_t ino,ib_ino_info_t * ino_p)4507c478bd9Sstevel@tonic-gate ib_ino_map_reg_share(ib_t *ib_p, ib_ino_t ino, ib_ino_info_t *ino_p)
4517c478bd9Sstevel@tonic-gate {
4527c478bd9Sstevel@tonic-gate 	if (!IB_IS_OBIO_INO(ino)) {
4537c478bd9Sstevel@tonic-gate 		ASSERT(ino_p->ino_slot_no < 8);
4547c478bd9Sstevel@tonic-gate 		ib_p->ib_map_reg_counters[ino_p->ino_slot_no]++;
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate }
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate /*
4597c478bd9Sstevel@tonic-gate  * return true if the ino shares mapping register with other interrupts
4607c478bd9Sstevel@tonic-gate  * of the same slot, or is still shared by other On-board devices.
4617c478bd9Sstevel@tonic-gate  */
4627c478bd9Sstevel@tonic-gate int
ib_ino_map_reg_unshare(ib_t * ib_p,ib_ino_t ino,ib_ino_info_t * ino_p)4637c478bd9Sstevel@tonic-gate ib_ino_map_reg_unshare(ib_t *ib_p, ib_ino_t ino, ib_ino_info_t *ino_p)
4647c478bd9Sstevel@tonic-gate {
4657c478bd9Sstevel@tonic-gate 	ASSERT(IB_IS_OBIO_INO(ino) || ino_p->ino_slot_no < 8);
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	if (IB_IS_OBIO_INO(ino))
468b0fc0e77Sgovinda 		return (ino_p->ino_ipil_size);
4697c478bd9Sstevel@tonic-gate 	else
4707c478bd9Sstevel@tonic-gate 		return (--ib_p->ib_map_reg_counters[ino_p->ino_slot_no]);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4747c478bd9Sstevel@tonic-gate void
pci_pbm_intr_dist(pbm_t * pbm_p)4757c478bd9Sstevel@tonic-gate pci_pbm_intr_dist(pbm_t *pbm_p)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate uintptr_t
pci_ib_setup(ib_t * ib_p)4807c478bd9Sstevel@tonic-gate pci_ib_setup(ib_t *ib_p)
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate 	pci_t *pci_p = ib_p->ib_pci_p;
4837c478bd9Sstevel@tonic-gate 	uintptr_t a = get_reg_base(pci_p);
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	ib_p->ib_ign = PCI_ID_TO_IGN(pci_p->pci_id);
4867c478bd9Sstevel@tonic-gate 	ib_p->ib_max_ino = PSYCHO_MAX_INO;
4877c478bd9Sstevel@tonic-gate 	ib_p->ib_slot_intr_map_regs = a + PSYCHO_IB_SLOT_INTR_MAP_REG_OFFSET;
4887c478bd9Sstevel@tonic-gate 	ib_p->ib_obio_intr_map_regs = a + PSYCHO_IB_OBIO_INTR_MAP_REG_OFFSET;
4897c478bd9Sstevel@tonic-gate 	ib_p->ib_obio_clear_intr_regs =
4907c478bd9Sstevel@tonic-gate 		a + PSYCHO_IB_OBIO_CLEAR_INTR_REG_OFFSET;
4917c478bd9Sstevel@tonic-gate 	return (a);
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate uint32_t
pci_xlate_intr(dev_info_t * dip,dev_info_t * rdip,ib_t * ib_p,uint32_t intr)4957c478bd9Sstevel@tonic-gate pci_xlate_intr(dev_info_t *dip, dev_info_t *rdip, ib_t *ib_p, uint32_t intr)
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate 	int32_t len;
4987c478bd9Sstevel@tonic-gate 	dev_info_t *cdip;
4997c478bd9Sstevel@tonic-gate 	pci_regspec_t *pci_rp;
5007c478bd9Sstevel@tonic-gate 	uint32_t bus, dev, phys_hi;
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	if ((intr > PCI_INTD) || (intr < PCI_INTA))
5037c478bd9Sstevel@tonic-gate 		goto done;
5047c478bd9Sstevel@tonic-gate 	if (ddi_prop_exists(DDI_DEV_T_ANY, rdip, NULL, "interrupt-map"))
5057c478bd9Sstevel@tonic-gate 		goto done;
5067c478bd9Sstevel@tonic-gate 	/*
5077c478bd9Sstevel@tonic-gate 	 * Hack for pre 1275 imap machines e.g. quark & tazmo
5087c478bd9Sstevel@tonic-gate 	 * We need to turn any PCI interrupts into ino interrupts.  machines
5097c478bd9Sstevel@tonic-gate 	 * supporting imap will have this done in the map.
5107c478bd9Sstevel@tonic-gate 	 */
5117c478bd9Sstevel@tonic-gate 	cdip = get_my_childs_dip(dip, rdip);
5127c478bd9Sstevel@tonic-gate 	if (ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, "reg",
5137c478bd9Sstevel@tonic-gate 		(caddr_t)&pci_rp, &len) != DDI_SUCCESS)
5147c478bd9Sstevel@tonic-gate 		return (0);
5157c478bd9Sstevel@tonic-gate 	phys_hi = pci_rp->pci_phys_hi;
5167c478bd9Sstevel@tonic-gate 	kmem_free(pci_rp, len);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	bus = PCI_REG_BUS_G(phys_hi);
5197c478bd9Sstevel@tonic-gate 	dev = PCI_REG_DEV_G(phys_hi);
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	/*
5227c478bd9Sstevel@tonic-gate 	 * The ino for a given device id is derived as 0BSSNN where
5237c478bd9Sstevel@tonic-gate 	 *
5247c478bd9Sstevel@tonic-gate 	 *	B = 0 for bus A, 1 for bus B
5257c478bd9Sstevel@tonic-gate 	 *	SS = dev - 1 for bus A, dev - 2 for bus B
5267c478bd9Sstevel@tonic-gate 	 *	NN = 00 for INTA#, 01 for INTB#, 10 for INTC#, 11 for INTD#
5277c478bd9Sstevel@tonic-gate 	 *
5287c478bd9Sstevel@tonic-gate 	 * if pci bus number > 0x80, then devices are located on the A side(66)
5297c478bd9Sstevel@tonic-gate 	 */
5307c478bd9Sstevel@tonic-gate 	DEBUG3(DBG_IB, dip, "pci_xlate_intr: bus=%x, dev=%x, intr=%x\n",
5317c478bd9Sstevel@tonic-gate 		bus, dev, intr);
5327c478bd9Sstevel@tonic-gate 	intr--;
5337c478bd9Sstevel@tonic-gate 	intr |= (bus & 0x80) ? ((dev - 1) << 2) : (0x10 | ((dev - 2) << 2));
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_IB, dip, "pci_xlate_intr: done ino=%x\n", intr);
5367c478bd9Sstevel@tonic-gate done:
5377c478bd9Sstevel@tonic-gate 	return (IB_INO_TO_MONDO(ib_p, intr));
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate  * Return the cpuid to to be used for an ino. Psycho has special slot-cpu
5427c478bd9Sstevel@tonic-gate  * constraints on cpu assignment:
5437c478bd9Sstevel@tonic-gate  *
5447c478bd9Sstevel@tonic-gate  * On multi-function pci cards, functions have separate devinfo nodes and
5457c478bd9Sstevel@tonic-gate  * interrupts. Some pci support hardware, such as the psycho/pcipsy chip,
5467c478bd9Sstevel@tonic-gate  * control interrupt-to-cpu binding on a per pci-slot basis instead of per
5477c478bd9Sstevel@tonic-gate  * function.  For hardware like this, if an interrupt for one function has
5487c478bd9Sstevel@tonic-gate  * already been directed to a particular cpu, we can't choose a different
5497c478bd9Sstevel@tonic-gate  * cpu for another function implemented in the same pci-slot - if we did
5507c478bd9Sstevel@tonic-gate  * we would be redirecting the first function too (which causes problems
5517c478bd9Sstevel@tonic-gate  * for consistent interrupt distribution).
5527c478bd9Sstevel@tonic-gate  *
5537c478bd9Sstevel@tonic-gate  * This function determines if there is already an established slot-oriented
5547c478bd9Sstevel@tonic-gate  * interrupt-to-cpu binding established, if there is then it returns that
5557c478bd9Sstevel@tonic-gate  * cpu.  Otherwise a new cpu is selected by intr_dist_cpuid().
5567c478bd9Sstevel@tonic-gate  *
5577c478bd9Sstevel@tonic-gate  * The devinfo node we are trying to associate a cpu with is
558b0fc0e77Sgovinda  * ino_p->ino_ipil_p->ipil_ih_head->ih_dip.
5597c478bd9Sstevel@tonic-gate  */
5607c478bd9Sstevel@tonic-gate uint32_t
pci_intr_dist_cpuid(ib_t * ib_p,ib_ino_info_t * ino_p)5617c478bd9Sstevel@tonic-gate pci_intr_dist_cpuid(ib_t *ib_p, ib_ino_info_t *ino_p)
5627c478bd9Sstevel@tonic-gate {
563b0fc0e77Sgovinda 	dev_info_t	*rdip = ino_p->ino_ipil_p->ipil_ih_head->ih_dip;
5647c478bd9Sstevel@tonic-gate 	dev_info_t	*prdip = ddi_get_parent(rdip);
5657c478bd9Sstevel@tonic-gate 	ib_ino_info_t	*sino_p;
5667c478bd9Sstevel@tonic-gate 	dev_info_t	*sdip;
5677c478bd9Sstevel@tonic-gate 	dev_info_t	*psdip;
5687c478bd9Sstevel@tonic-gate 	char		*buf1 = NULL, *buf2 = NULL;
5697c478bd9Sstevel@tonic-gate 	char		*s1, *s2, *s3;
5707c478bd9Sstevel@tonic-gate 	int		l2;
5717c478bd9Sstevel@tonic-gate 	int		cpu_id;
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	/* must be psycho driver parent (not ebus) */
5747c478bd9Sstevel@tonic-gate 	if (strcmp(ddi_driver_name(prdip), "pcipsy") != 0)
5757c478bd9Sstevel@tonic-gate 		goto newcpu;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	/*
5787c478bd9Sstevel@tonic-gate 	 * From PCI 1275 binding: 2.2.1.3 Unit Address representation:
5797c478bd9Sstevel@tonic-gate 	 *   Since the "unit-number" is the address that appears in on Open
5807c478bd9Sstevel@tonic-gate 	 *   Firmware 'device path', it follows that only the DD and DD,FF
5817c478bd9Sstevel@tonic-gate 	 *   forms of the text representation can appear in a 'device path'.
5827c478bd9Sstevel@tonic-gate 	 *
5837c478bd9Sstevel@tonic-gate 	 * The rdip unit address is of the form "DD[,FF]".  Define two
5847c478bd9Sstevel@tonic-gate 	 * unit address strings that represent same-slot use: "DD" and "DD,".
5857c478bd9Sstevel@tonic-gate 	 * The first compare uses strcmp, the second uses strncmp.
5867c478bd9Sstevel@tonic-gate 	 */
5877c478bd9Sstevel@tonic-gate 	s1 = ddi_get_name_addr(rdip);
5887c478bd9Sstevel@tonic-gate 	if (s1 == NULL)
5897c478bd9Sstevel@tonic-gate 		goto newcpu;
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	buf1 = kmem_alloc(MAXNAMELEN, KM_SLEEP);	/* strcmp */
5927c478bd9Sstevel@tonic-gate 	buf2 = kmem_alloc(MAXNAMELEN, KM_SLEEP);	/* strncmp */
5937c478bd9Sstevel@tonic-gate 	s1 = strcpy(buf1, s1);
5947c478bd9Sstevel@tonic-gate 	s2 = strcpy(buf2, s1);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	s1 = strrchr(s1, ',');
5977c478bd9Sstevel@tonic-gate 	if (s1) {
5987c478bd9Sstevel@tonic-gate 		*s1 = '\0';			/* have "DD,FF" */
5997c478bd9Sstevel@tonic-gate 		s1 = buf1;			/* search via strcmp "DD" */
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 		s2 = strrchr(s2, ',');
6027c478bd9Sstevel@tonic-gate 		*(s2 + 1) = '\0';
6037c478bd9Sstevel@tonic-gate 		s2 = buf2;
6047c478bd9Sstevel@tonic-gate 		l2 = strlen(s2);		/* search via strncmp "DD," */
6057c478bd9Sstevel@tonic-gate 	} else {
6067c478bd9Sstevel@tonic-gate 		(void) strcat(s2, ",");		/* have "DD" */
6077c478bd9Sstevel@tonic-gate 		l2 = strlen(s2);		/* search via strncmp "DD," */
6087c478bd9Sstevel@tonic-gate 	}
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	/*
6117c478bd9Sstevel@tonic-gate 	 * Search the established ino list for devinfo nodes bound
6127c478bd9Sstevel@tonic-gate 	 * to an ino that matches one of the slot use strings.
6137c478bd9Sstevel@tonic-gate 	 */
6147c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
615b0fc0e77Sgovinda 	for (sino_p = ib_p->ib_ino_lst; sino_p; sino_p = sino_p->ino_next_p) {
6167c478bd9Sstevel@tonic-gate 		/* skip self and non-established */
6177c478bd9Sstevel@tonic-gate 		if ((sino_p == ino_p) || (sino_p->ino_established == 0))
6187c478bd9Sstevel@tonic-gate 			continue;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 		/* skip non-siblings */
621b0fc0e77Sgovinda 		sdip = sino_p->ino_ipil_p->ipil_ih_head->ih_dip;
6227c478bd9Sstevel@tonic-gate 		psdip = ddi_get_parent(sdip);
6237c478bd9Sstevel@tonic-gate 		if (psdip != prdip)
6247c478bd9Sstevel@tonic-gate 			continue;
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		/* must be psycho driver parent (not ebus) */
6277c478bd9Sstevel@tonic-gate 		if (strcmp(ddi_driver_name(psdip), "pcipsy") != 0)
6287c478bd9Sstevel@tonic-gate 			continue;
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 		s3 = ddi_get_name_addr(sdip);
6317c478bd9Sstevel@tonic-gate 		if ((s1 && (strcmp(s1, s3) == 0)) ||
6327c478bd9Sstevel@tonic-gate 		    (strncmp(s2, s3, l2) == 0)) {
6337c478bd9Sstevel@tonic-gate 			extern int intr_dist_debug;
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 			if (intr_dist_debug)
6367c478bd9Sstevel@tonic-gate 				cmn_err(CE_CONT, "intr_dist: "
6377c478bd9Sstevel@tonic-gate 				    "pcipsy`pci_intr_dist_cpuid "
6387c478bd9Sstevel@tonic-gate 				    "%s#%d %s: cpu %d established "
6397c478bd9Sstevel@tonic-gate 				    "by %s#%d %s\n", ddi_driver_name(rdip),
6407c478bd9Sstevel@tonic-gate 				    ddi_get_instance(rdip),
6417c478bd9Sstevel@tonic-gate 				    ddi_deviname(rdip, buf1), sino_p->ino_cpuid,
6427c478bd9Sstevel@tonic-gate 				    ddi_driver_name(sdip),
6437c478bd9Sstevel@tonic-gate 				    ddi_get_instance(sdip),
6447c478bd9Sstevel@tonic-gate 				    ddi_deviname(sdip, buf2));
6457c478bd9Sstevel@tonic-gate 			break;
6467c478bd9Sstevel@tonic-gate 		}
6477c478bd9Sstevel@tonic-gate 	}
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	/* If a slot use match is found then use established cpu */
6507c478bd9Sstevel@tonic-gate 	if (sino_p) {
6517c478bd9Sstevel@tonic-gate 		cpu_id = sino_p->ino_cpuid;	/* target established cpu */
6527c478bd9Sstevel@tonic-gate 		goto out;
6537c478bd9Sstevel@tonic-gate 	}
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate newcpu:	cpu_id = intr_dist_cpuid();		/* target new cpu */
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate out:	if (buf1)
6587c478bd9Sstevel@tonic-gate 		kmem_free(buf1, MAXNAMELEN);
6597c478bd9Sstevel@tonic-gate 	if (buf2)
6607c478bd9Sstevel@tonic-gate 		kmem_free(buf2, MAXNAMELEN);
6617c478bd9Sstevel@tonic-gate 	return (cpu_id);
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6669129170aSarutz static void
cb_thermal_timeout(void * arg)6679129170aSarutz cb_thermal_timeout(void *arg)
6687c478bd9Sstevel@tonic-gate {
6697c478bd9Sstevel@tonic-gate 	do_shutdown();
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate 	/*
6727c478bd9Sstevel@tonic-gate 	 * In case do_shutdown() fails to halt the system.
6737c478bd9Sstevel@tonic-gate 	 */
6747c478bd9Sstevel@tonic-gate 	(void) timeout((void(*)(void *))power_down, NULL,
6757c478bd9Sstevel@tonic-gate 	    thermal_powerdown_delay * hz);
6767c478bd9Sstevel@tonic-gate }
6779129170aSarutz 
6789129170aSarutz /*
6799129170aSarutz  * High-level handler for psycho's CBNINTR_THERMAL interrupt.
6809129170aSarutz  *
6819129170aSarutz  * Use timeout(9f) to implement the core functionality so that the
6829129170aSarutz  * timeout(9f) function can sleep, if needed.
6839129170aSarutz  */
6849129170aSarutz /*ARGSUSED*/
6859129170aSarutz uint_t
cb_thermal_intr(caddr_t a)6869129170aSarutz cb_thermal_intr(caddr_t a)
6879129170aSarutz {
6889129170aSarutz 	cmn_err(CE_WARN, "pci: Thermal warning detected!\n");
6899129170aSarutz 	if (pci_thermal_intr_fatal) {
6909129170aSarutz 		(void) timeout(cb_thermal_timeout, NULL, 0);
6919129170aSarutz 	}
6927c478bd9Sstevel@tonic-gate 	return (DDI_INTR_CLAIMED);
6937c478bd9Sstevel@tonic-gate }
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate void
pci_cb_teardown(pci_t * pci_p)6967c478bd9Sstevel@tonic-gate pci_cb_teardown(pci_t *pci_p)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate 	cb_t	*cb_p = pci_p->pci_cb_p;
6997c478bd9Sstevel@tonic-gate 	uint32_t mondo;
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	if (pci_p->pci_thermal_interrupt != -1) {
7027c478bd9Sstevel@tonic-gate 		mondo = ((pci_p->pci_cb_p->cb_ign  << PCI_INO_BITS) |
7037c478bd9Sstevel@tonic-gate 		    pci_p->pci_inos[CBNINTR_THERMAL]);
7047c478bd9Sstevel@tonic-gate 		mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 		cb_disable_nintr(cb_p, CBNINTR_THERMAL, IB_INTR_WAIT);
707b0fc0e77Sgovinda 		VERIFY(rem_ivintr(mondo, pci_pil[CBNINTR_THERMAL]) == 0);
7087c478bd9Sstevel@tonic-gate 	}
7097c478bd9Sstevel@tonic-gate #ifdef _STARFIRE
7107c478bd9Sstevel@tonic-gate 	pc_ittrans_uninit(cb_p->cb_ittrans_cookie);
7117c478bd9Sstevel@tonic-gate #endif /* _STARFIRE */
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate int
cb_register_intr(pci_t * pci_p)7157c478bd9Sstevel@tonic-gate cb_register_intr(pci_t *pci_p)
7167c478bd9Sstevel@tonic-gate {
7177c478bd9Sstevel@tonic-gate 	uint32_t mondo;
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	if (pci_p->pci_thermal_interrupt == -1)
7207c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
7237c478bd9Sstevel@tonic-gate 	    pci_p->pci_inos[CBNINTR_THERMAL]);
7247c478bd9Sstevel@tonic-gate 	mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	VERIFY(add_ivintr(mondo, pci_pil[CBNINTR_THERMAL],
727b0fc0e77Sgovinda 	    (intrfunc)cb_thermal_intr, (caddr_t)pci_p->pci_cb_p,
728b0fc0e77Sgovinda 	    NULL, NULL) == 0);
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	return (PCI_ATTACH_RETCODE(PCI_CB_OBJ, PCI_OBJ_INTR_ADD, DDI_SUCCESS));
7317c478bd9Sstevel@tonic-gate }
7327c478bd9Sstevel@tonic-gate 
7337c478bd9Sstevel@tonic-gate void
cb_enable_intr(pci_t * pci_p)7347c478bd9Sstevel@tonic-gate cb_enable_intr(pci_t *pci_p)
7357c478bd9Sstevel@tonic-gate {
7367c478bd9Sstevel@tonic-gate 	if (pci_p->pci_thermal_interrupt != -1)
7377c478bd9Sstevel@tonic-gate 		cb_enable_nintr(pci_p, CBNINTR_THERMAL);
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate uint64_t
cb_ino_to_map_pa(cb_t * cb_p,ib_ino_t ino)7417c478bd9Sstevel@tonic-gate cb_ino_to_map_pa(cb_t *cb_p, ib_ino_t ino)
7427c478bd9Sstevel@tonic-gate {
7437c478bd9Sstevel@tonic-gate 	return (cb_p->cb_map_pa + ((ino & 0x1f) << 3));
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate uint64_t
cb_ino_to_clr_pa(cb_t * cb_p,ib_ino_t ino)7477c478bd9Sstevel@tonic-gate cb_ino_to_clr_pa(cb_t *cb_p, ib_ino_t ino)
7487c478bd9Sstevel@tonic-gate {
7497c478bd9Sstevel@tonic-gate 	return (cb_p->cb_clr_pa + ((ino & 0x1f) << 3));
7507c478bd9Sstevel@tonic-gate }
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate /*
7537c478bd9Sstevel@tonic-gate  * allow removal of exported/shared thermal interrupt
7547c478bd9Sstevel@tonic-gate  */
7557c478bd9Sstevel@tonic-gate int
cb_remove_xintr(pci_t * pci_p,dev_info_t * dip,dev_info_t * rdip,ib_ino_t ino,ib_mondo_t mondo)7567c478bd9Sstevel@tonic-gate cb_remove_xintr(pci_t *pci_p, dev_info_t *dip, dev_info_t *rdip,
7577c478bd9Sstevel@tonic-gate 	ib_ino_t ino, ib_mondo_t mondo)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate 	if (ino != pci_p->pci_inos[CBNINTR_THERMAL])
7607c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	cb_disable_nintr(pci_p->pci_cb_p, CBNINTR_THERMAL, IB_INTR_WAIT);
763b0fc0e77Sgovinda 	VERIFY(rem_ivintr(mondo, pci_pil[CBNINTR_THERMAL]) == 0);
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_R_INTX, dip, "remove xintr %x\n", ino);
7667c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate int
pci_ecc_add_intr(pci_t * pci_p,int inum,ecc_intr_info_t * eii_p)7707c478bd9Sstevel@tonic-gate pci_ecc_add_intr(pci_t *pci_p, int inum, ecc_intr_info_t *eii_p)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate 	uint32_t mondo;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
7757c478bd9Sstevel@tonic-gate 	    pci_p->pci_inos[inum]);
7767c478bd9Sstevel@tonic-gate 	mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7777c478bd9Sstevel@tonic-gate 
778b0fc0e77Sgovinda 	VERIFY(add_ivintr(mondo, pci_pil[inum], (intrfunc)ecc_intr,
779b0fc0e77Sgovinda 	    (caddr_t)eii_p, NULL, NULL) == 0);
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	return (PCI_ATTACH_RETCODE(PCI_ECC_OBJ, PCI_OBJ_INTR_ADD, DDI_SUCCESS));
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate void
pci_ecc_rem_intr(pci_t * pci_p,int inum,ecc_intr_info_t * eii_p)7857c478bd9Sstevel@tonic-gate pci_ecc_rem_intr(pci_t *pci_p, int inum, ecc_intr_info_t *eii_p)
7867c478bd9Sstevel@tonic-gate {
7877c478bd9Sstevel@tonic-gate 	uint32_t mondo;
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate 	mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
7907c478bd9Sstevel@tonic-gate 	    pci_p->pci_inos[inum]);
7917c478bd9Sstevel@tonic-gate 	mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7927c478bd9Sstevel@tonic-gate 
793b0fc0e77Sgovinda 	VERIFY(rem_ivintr(mondo, pci_pil[inum]) == 0);
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate static int pbm_has_pass_1_cheerio(pci_t *pci_p);
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate void
pbm_configure(pbm_t * pbm_p)7997c478bd9Sstevel@tonic-gate pbm_configure(pbm_t *pbm_p)
8007c478bd9Sstevel@tonic-gate {
8017c478bd9Sstevel@tonic-gate 	pci_t *pci_p = pbm_p->pbm_pci_p;
8027c478bd9Sstevel@tonic-gate 	cb_t *cb_p = pci_p->pci_cb_p;
8037c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pci_p->pci_dip;
8047c478bd9Sstevel@tonic-gate 	int instance = ddi_get_instance(dip);
8057c478bd9Sstevel@tonic-gate 	uint32_t mask = 1 << instance;
8067c478bd9Sstevel@tonic-gate 	uint64_t l;
8077c478bd9Sstevel@tonic-gate 	uint16_t s = 0;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	/*
8107c478bd9Sstevel@tonic-gate 	 * Workarounds for hardware bugs:
8117c478bd9Sstevel@tonic-gate 	 *
8127c478bd9Sstevel@tonic-gate 	 * bus parking
8137c478bd9Sstevel@tonic-gate 	 *
8147c478bd9Sstevel@tonic-gate 	 *	Pass 2 psycho parts have a bug that requires bus
8157c478bd9Sstevel@tonic-gate 	 *	parking to be disabled.
8167c478bd9Sstevel@tonic-gate 	 *
8177c478bd9Sstevel@tonic-gate 	 *	Pass 1 cheerio parts have a bug which prevents them
8187c478bd9Sstevel@tonic-gate 	 *	from working on a PBM with bus parking enabled.
8197c478bd9Sstevel@tonic-gate 	 *
8207c478bd9Sstevel@tonic-gate 	 * rerun disable
8217c478bd9Sstevel@tonic-gate 	 *
8227c478bd9Sstevel@tonic-gate 	 *	Pass 1 and 2 psycho's require that the rerun's be
8237c478bd9Sstevel@tonic-gate 	 *	enabled.
8247c478bd9Sstevel@tonic-gate 	 *
8257c478bd9Sstevel@tonic-gate 	 * retry limit
8267c478bd9Sstevel@tonic-gate 	 *
8277c478bd9Sstevel@tonic-gate 	 *	For pass 1 and pass 2 psycho parts we disable the
8287c478bd9Sstevel@tonic-gate 	 *	retry limit.  This is because the limit of 16 seems
8297c478bd9Sstevel@tonic-gate 	 *	too restrictive for devices that are children of pci
8307c478bd9Sstevel@tonic-gate 	 *	to pci bridges.  For pass 3 this limit will be 64.
8317c478bd9Sstevel@tonic-gate 	 *
8327c478bd9Sstevel@tonic-gate 	 * DMA write/PIO read sync
8337c478bd9Sstevel@tonic-gate 	 *
8347c478bd9Sstevel@tonic-gate 	 *	For pass 2 psycho, the disable this feature.
8357c478bd9Sstevel@tonic-gate 	 */
8367c478bd9Sstevel@tonic-gate 	l = lddphysio(cb_p->cb_base_pa + PSYCHO_CB_CONTROL_STATUS_REG_OFFSET);
8377c478bd9Sstevel@tonic-gate 	l &= PSYCHO_CB_CONTROL_STATUS_VER;
8387c478bd9Sstevel@tonic-gate 	l >>= PSYCHO_CB_CONTROL_STATUS_VER_SHIFT;
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 	DEBUG2(DBG_ATTACH, dip, "cb_create: ver=%d, mask=%x\n", l, mask);
8417c478bd9Sstevel@tonic-gate 	pci_rerun_disable = (uint32_t)-1;
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	switch (l) {
8447c478bd9Sstevel@tonic-gate 	case 0:
8457c478bd9Sstevel@tonic-gate 		DEBUG0(DBG_ATTACH, dip, "cb_create: psycho pass 1\n");
8467c478bd9Sstevel@tonic-gate 		if (!pci_disable_pass1_workarounds) {
8477c478bd9Sstevel@tonic-gate 			if (pbm_has_pass_1_cheerio(pci_p))
8487c478bd9Sstevel@tonic-gate 				pci_bus_parking_enable &= ~mask;
8497c478bd9Sstevel@tonic-gate 			pci_rerun_disable &= ~mask;
8507c478bd9Sstevel@tonic-gate 			pci_retry_disable |= mask;
8517c478bd9Sstevel@tonic-gate 		}
8527c478bd9Sstevel@tonic-gate 		break;
8537c478bd9Sstevel@tonic-gate 	case 1:
8547c478bd9Sstevel@tonic-gate 		if (!pci_disable_pass2_workarounds) {
8557c478bd9Sstevel@tonic-gate 			pci_bus_parking_enable &= ~mask;
8567c478bd9Sstevel@tonic-gate 			pci_rerun_disable &= ~mask;
8577c478bd9Sstevel@tonic-gate 			pci_retry_disable |= mask;
8587c478bd9Sstevel@tonic-gate 			pci_dwsync_disable |= mask;
8597c478bd9Sstevel@tonic-gate 		}
8607c478bd9Sstevel@tonic-gate 		break;
8617c478bd9Sstevel@tonic-gate 	case 2:
8627c478bd9Sstevel@tonic-gate 		if (!pci_disable_pass3_workarounds) {
8637c478bd9Sstevel@tonic-gate 			pci_dwsync_disable |= mask;
8647c478bd9Sstevel@tonic-gate 			if (pbm_has_pass_1_cheerio(pci_p))
8657c478bd9Sstevel@tonic-gate 				pci_bus_parking_enable &= ~mask;
8667c478bd9Sstevel@tonic-gate 		}
8677c478bd9Sstevel@tonic-gate 		break;
8687c478bd9Sstevel@tonic-gate 	case 3:
8697c478bd9Sstevel@tonic-gate 		if (!pci_disable_plus_workarounds) {
8707c478bd9Sstevel@tonic-gate 			pci_dwsync_disable |= mask;
8717c478bd9Sstevel@tonic-gate 			if (pbm_has_pass_1_cheerio(pci_p))
8727c478bd9Sstevel@tonic-gate 				pci_bus_parking_enable &= ~mask;
8737c478bd9Sstevel@tonic-gate 		}
8747c478bd9Sstevel@tonic-gate 		break;
8757c478bd9Sstevel@tonic-gate 	default:
8767c478bd9Sstevel@tonic-gate 		if (!pci_disable_default_workarounds) {
8777c478bd9Sstevel@tonic-gate 			pci_dwsync_disable |= mask;
8787c478bd9Sstevel@tonic-gate 			if (pbm_has_pass_1_cheerio(pci_p))
8797c478bd9Sstevel@tonic-gate 				pci_bus_parking_enable &= ~mask;
8807c478bd9Sstevel@tonic-gate 		}
8817c478bd9Sstevel@tonic-gate 		break;
8827c478bd9Sstevel@tonic-gate 	}
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 	/*
8857c478bd9Sstevel@tonic-gate 	 * Clear any PBM errors.
8867c478bd9Sstevel@tonic-gate 	 */
8877c478bd9Sstevel@tonic-gate 	l = (PSYCHO_PCI_AFSR_E_MASK << PSYCHO_PCI_AFSR_PE_SHIFT) |
8887c478bd9Sstevel@tonic-gate 		(PSYCHO_PCI_AFSR_E_MASK << PSYCHO_PCI_AFSR_SE_SHIFT);
8897c478bd9Sstevel@tonic-gate 	*pbm_p->pbm_async_flt_status_reg = l;
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	/*
8927c478bd9Sstevel@tonic-gate 	 * Clear error bits in configuration status register.
8937c478bd9Sstevel@tonic-gate 	 */
8947c478bd9Sstevel@tonic-gate 	s = PCI_STAT_PERROR | PCI_STAT_S_PERROR |
8957c478bd9Sstevel@tonic-gate 		PCI_STAT_R_MAST_AB | PCI_STAT_R_TARG_AB |
8967c478bd9Sstevel@tonic-gate 		PCI_STAT_S_TARG_AB | PCI_STAT_S_PERROR;
8977c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf status reg=%x\n", s);
8987c478bd9Sstevel@tonic-gate 	pbm_p->pbm_config_header->ch_status_reg = s;
8997c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf status reg==%x\n",
9007c478bd9Sstevel@tonic-gate 		pbm_p->pbm_config_header->ch_status_reg);
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	l = *pbm_p->pbm_ctrl_reg;	/* save control register state */
9037c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: ctrl reg==%llx\n", l);
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	/*
9067c478bd9Sstevel@tonic-gate 	 * See if any SERR# signals are asserted.  We'll clear them later.
9077c478bd9Sstevel@tonic-gate 	 */
9087c478bd9Sstevel@tonic-gate 	if (l & COMMON_PCI_CTRL_SERR)
9097c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s%d: SERR asserted on pci bus\n",
9107c478bd9Sstevel@tonic-gate 		    ddi_driver_name(dip), instance);
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 	/*
9137c478bd9Sstevel@tonic-gate 	 * Determine if PCI bus is running at 33 or 66 mhz.
9147c478bd9Sstevel@tonic-gate 	 */
9157c478bd9Sstevel@tonic-gate 	if (l & COMMON_PCI_CTRL_SPEED)
9167c478bd9Sstevel@tonic-gate 		pbm_p->pbm_speed = PBM_SPEED_66MHZ;
9177c478bd9Sstevel@tonic-gate 	else
9187c478bd9Sstevel@tonic-gate 		pbm_p->pbm_speed = PBM_SPEED_33MHZ;
9197c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: %d mhz\n",
9207c478bd9Sstevel@tonic-gate 	    pbm_p->pbm_speed  == PBM_SPEED_66MHZ ? 66 : 33);
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	/*
9237c478bd9Sstevel@tonic-gate 	 * Enable error interrupts.
9247c478bd9Sstevel@tonic-gate 	 */
9257c478bd9Sstevel@tonic-gate 	if (pci_error_intr_enable & mask)
9267c478bd9Sstevel@tonic-gate 		l |= PSYCHO_PCI_CTRL_ERR_INT_EN;
9277c478bd9Sstevel@tonic-gate 	else
9287c478bd9Sstevel@tonic-gate 		l &= ~PSYCHO_PCI_CTRL_ERR_INT_EN;
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate 	/*
9317c478bd9Sstevel@tonic-gate 	 * Disable pci streaming byte errors and error interrupts.
9327c478bd9Sstevel@tonic-gate 	 */
9337c478bd9Sstevel@tonic-gate 	pci_sbh_error_intr_enable &= ~mask;
9347c478bd9Sstevel@tonic-gate 	l &= ~PSYCHO_PCI_CTRL_SBH_INT_EN;
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	/*
9377c478bd9Sstevel@tonic-gate 	 * Enable/disable bus parking.
9387c478bd9Sstevel@tonic-gate 	 */
9397c478bd9Sstevel@tonic-gate 	if ((pci_bus_parking_enable & mask) &&
9407c478bd9Sstevel@tonic-gate 	    !ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
9417c478bd9Sstevel@tonic-gate 	    "no-bus-parking"))
9427c478bd9Sstevel@tonic-gate 		l |= PSYCHO_PCI_CTRL_ARB_PARK;
9437c478bd9Sstevel@tonic-gate 	else
9447c478bd9Sstevel@tonic-gate 		l &= ~PSYCHO_PCI_CTRL_ARB_PARK;
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	/*
9477c478bd9Sstevel@tonic-gate 	 * Enable arbitration.
9487c478bd9Sstevel@tonic-gate 	 */
9497c478bd9Sstevel@tonic-gate 	if (pci_p->pci_side == B)
9507c478bd9Sstevel@tonic-gate 		l = (l & ~PSYCHO_PCI_CTRL_ARB_EN_MASK) | pci_b_arb_enable;
9517c478bd9Sstevel@tonic-gate 	else
9527c478bd9Sstevel@tonic-gate 		l = (l & ~PSYCHO_PCI_CTRL_ARB_EN_MASK) | pci_a_arb_enable;
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate 	/*
9557c478bd9Sstevel@tonic-gate 	 * Make sure SERR is clear
9567c478bd9Sstevel@tonic-gate 	 */
9577c478bd9Sstevel@tonic-gate 	l |= COMMON_PCI_CTRL_SERR;
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate 	/*
9607c478bd9Sstevel@tonic-gate 	 * Make sure power management interrupt is disabled.
9617c478bd9Sstevel@tonic-gate 	 */
9627c478bd9Sstevel@tonic-gate 	l &= ~PSYCHO_PCI_CTRL_WAKEUP_EN;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate #ifdef _STARFIRE
9657c478bd9Sstevel@tonic-gate 	/*
9667c478bd9Sstevel@tonic-gate 	 * Hack to determine whether we do Starfire special handling
9677c478bd9Sstevel@tonic-gate 	 * For starfire, we simply program a constant odd-value
9687c478bd9Sstevel@tonic-gate 	 * (0x1D) in the MID field.
9697c478bd9Sstevel@tonic-gate 	 *
9707c478bd9Sstevel@tonic-gate 	 * Zero out the MID field before ORing. We leave the LSB of
9717c478bd9Sstevel@tonic-gate 	 * the MID field intact since we cannot have a zero (even)
9727c478bd9Sstevel@tonic-gate 	 * MID value.
9737c478bd9Sstevel@tonic-gate 	 */
9747c478bd9Sstevel@tonic-gate 	l &= 0xFF0FFFFFFFFFFFFFULL;
9757c478bd9Sstevel@tonic-gate 	l |= 0x1DULL << 51;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	/*
9787c478bd9Sstevel@tonic-gate 	 * Program in the Interrupt Group Number.  Here we have to
9797c478bd9Sstevel@tonic-gate 	 * convert the starfire 7bit upaid into a 5bit value.
9807c478bd9Sstevel@tonic-gate 	 */
9817c478bd9Sstevel@tonic-gate 	l |= (uint64_t)STARFIRE_UPAID2HWIGN(pbm_p->pbm_pci_p->pci_id)
9827c478bd9Sstevel@tonic-gate 		<< COMMON_CB_CONTROL_STATUS_IGN_SHIFT;
9837c478bd9Sstevel@tonic-gate #endif /* _STARFIRE */
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	/*
9867c478bd9Sstevel@tonic-gate 	 * Now finally write the control register with the appropriate value.
9877c478bd9Sstevel@tonic-gate 	 */
9887c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: ctrl reg=%llx\n", l);
9897c478bd9Sstevel@tonic-gate 	*pbm_p->pbm_ctrl_reg = l;
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate 	/*
9927c478bd9Sstevel@tonic-gate 	 * Allow the diag register to be set based upon variable that
9937c478bd9Sstevel@tonic-gate 	 * can be configured via /etc/system.
9947c478bd9Sstevel@tonic-gate 	 */
9957c478bd9Sstevel@tonic-gate 	l = *pbm_p->pbm_diag_reg;
9967c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: PCI diag reg==%llx\n", l);
9977c478bd9Sstevel@tonic-gate 	if (pci_retry_disable & mask)
9987c478bd9Sstevel@tonic-gate 		l |= COMMON_PCI_DIAG_DIS_RETRY;
9997c478bd9Sstevel@tonic-gate 	if (pci_retry_enable & mask)
10007c478bd9Sstevel@tonic-gate 		l &= ~COMMON_PCI_DIAG_DIS_RETRY;
10017c478bd9Sstevel@tonic-gate 	if (pci_intsync_disable & mask)
10027c478bd9Sstevel@tonic-gate 		l |= COMMON_PCI_DIAG_DIS_INTSYNC;
10037c478bd9Sstevel@tonic-gate 	else
10047c478bd9Sstevel@tonic-gate 		l &= ~COMMON_PCI_DIAG_DIS_INTSYNC;
10057c478bd9Sstevel@tonic-gate 	if (pci_dwsync_disable & mask)
10067c478bd9Sstevel@tonic-gate 		l |= PSYCHO_PCI_DIAG_DIS_DWSYNC;
10077c478bd9Sstevel@tonic-gate 	else
10087c478bd9Sstevel@tonic-gate 		l &= ~PSYCHO_PCI_DIAG_DIS_DWSYNC;
10097c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: PCI diag reg=%llx\n", l);
10107c478bd9Sstevel@tonic-gate 	*pbm_p->pbm_diag_reg = l;
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	/*
10137c478bd9Sstevel@tonic-gate 	 * Enable SERR# and parity reporting via command register.
10147c478bd9Sstevel@tonic-gate 	 */
10157c478bd9Sstevel@tonic-gate 	s = pci_perr_enable & mask ? PCI_COMM_PARITY_DETECT : 0;
10167c478bd9Sstevel@tonic-gate 	s |= pci_serr_enable & mask ? PCI_COMM_SERR_ENABLE : 0;
10177c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf command reg=%x\n", s);
10187c478bd9Sstevel@tonic-gate 	pbm_p->pbm_config_header->ch_command_reg = s;
10197c478bd9Sstevel@tonic-gate 	DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf command reg==%x\n",
10207c478bd9Sstevel@tonic-gate 		pbm_p->pbm_config_header->ch_command_reg);
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	/*
10237c478bd9Sstevel@tonic-gate 	 * The current versions of the obp are suppose to set the latency
10247c478bd9Sstevel@tonic-gate 	 * timer register but do not.  Bug 1234181 is open against this
10257c478bd9Sstevel@tonic-gate 	 * problem.  Until this bug is fixed we check to see if the obp
10267c478bd9Sstevel@tonic-gate 	 * has attempted to set the latency timer register by checking
10277c478bd9Sstevel@tonic-gate 	 * for the existence of a "latency-timer" property.
10287c478bd9Sstevel@tonic-gate 	 */
10297c478bd9Sstevel@tonic-gate 	if (pci_set_latency_timer_register) {
10307c478bd9Sstevel@tonic-gate 		DEBUG1(DBG_ATTACH, dip,
10317c478bd9Sstevel@tonic-gate 		    "pbm_configure: set psycho latency timer to %x\n",
10327c478bd9Sstevel@tonic-gate 			pci_latency_timer);
10337c478bd9Sstevel@tonic-gate 		pbm_p->pbm_config_header->ch_latency_timer_reg =
10347c478bd9Sstevel@tonic-gate 			pci_latency_timer;
10357c478bd9Sstevel@tonic-gate 	}
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	(void) ndi_prop_update_int(DDI_DEV_T_ANY, dip, "latency-timer",
10387c478bd9Sstevel@tonic-gate 		(int)pbm_p->pbm_config_header->ch_latency_timer_reg);
10397c478bd9Sstevel@tonic-gate }
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate uint_t
pbm_disable_pci_errors(pbm_t * pbm_p)10427c478bd9Sstevel@tonic-gate pbm_disable_pci_errors(pbm_t *pbm_p)
10437c478bd9Sstevel@tonic-gate {
10447c478bd9Sstevel@tonic-gate 	pci_t *pci_p = pbm_p->pbm_pci_p;
10457c478bd9Sstevel@tonic-gate 	ib_t *ib_p = pci_p->pci_ib_p;
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	/*
10487c478bd9Sstevel@tonic-gate 	 * Disable error and streaming byte hole interrupts via the
10497c478bd9Sstevel@tonic-gate 	 * PBM control register.
10507c478bd9Sstevel@tonic-gate 	 */
10517c478bd9Sstevel@tonic-gate 	*pbm_p->pbm_ctrl_reg &=
10527c478bd9Sstevel@tonic-gate 		~(PSYCHO_PCI_CTRL_ERR_INT_EN | PSYCHO_PCI_CTRL_SBH_INT_EN);
10537c478bd9Sstevel@tonic-gate 
10547c478bd9Sstevel@tonic-gate 	/*
10557c478bd9Sstevel@tonic-gate 	 * Disable error interrupts via the interrupt mapping register.
10567c478bd9Sstevel@tonic-gate 	 */
10577c478bd9Sstevel@tonic-gate 	ib_intr_disable(ib_p, pci_p->pci_inos[CBNINTR_PBM], IB_INTR_NOWAIT);
10587c478bd9Sstevel@tonic-gate 	return (BF_NONE);
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10627c478bd9Sstevel@tonic-gate uint64_t
pci_sc_configure(pci_t * pci_p)10637c478bd9Sstevel@tonic-gate pci_sc_configure(pci_t *pci_p)
10647c478bd9Sstevel@tonic-gate {
10657c478bd9Sstevel@tonic-gate 	return (0);
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10697c478bd9Sstevel@tonic-gate void
pci_pbm_dma_sync(pbm_t * pbm_p,ib_ino_t ino)10707c478bd9Sstevel@tonic-gate pci_pbm_dma_sync(pbm_t *pbm_p, ib_ino_t ino)
10717c478bd9Sstevel@tonic-gate {
10727c478bd9Sstevel@tonic-gate 	uint64_t pa = pbm_p->pbm_sync_reg_pa;
10737c478bd9Sstevel@tonic-gate 	if (pa)
10747c478bd9Sstevel@tonic-gate 		(void) lddphysio(pa);		/* Load from Sync Register */
10757c478bd9Sstevel@tonic-gate }
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10787c478bd9Sstevel@tonic-gate dvma_context_t
pci_iommu_get_dvma_context(iommu_t * iommu_p,dvma_addr_t dvma_pg_index)10797c478bd9Sstevel@tonic-gate pci_iommu_get_dvma_context(iommu_t *iommu_p, dvma_addr_t dvma_pg_index)
10807c478bd9Sstevel@tonic-gate {
10817c478bd9Sstevel@tonic-gate 	ASSERT(0);
10827c478bd9Sstevel@tonic-gate 	return (0);
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10867c478bd9Sstevel@tonic-gate void
pci_iommu_free_dvma_context(iommu_t * iommu_p,dvma_context_t ctx)10877c478bd9Sstevel@tonic-gate pci_iommu_free_dvma_context(iommu_t *iommu_p, dvma_context_t ctx)
10887c478bd9Sstevel@tonic-gate {
10897c478bd9Sstevel@tonic-gate 	ASSERT(0);
10907c478bd9Sstevel@tonic-gate }
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate void
pci_iommu_config(iommu_t * iommu_p,uint64_t iommu_ctl,uint64_t cfgpa)10937c478bd9Sstevel@tonic-gate pci_iommu_config(iommu_t *iommu_p, uint64_t iommu_ctl, uint64_t cfgpa)
10947c478bd9Sstevel@tonic-gate {
10957c478bd9Sstevel@tonic-gate 	volatile uint64_t *pbm_csr_p = (volatile uint64_t *)
10967c478bd9Sstevel@tonic-gate 		get_pbm_reg_base(iommu_p->iommu_pci_p);
10977c478bd9Sstevel@tonic-gate 	volatile uint64_t pbm_ctl = *pbm_csr_p;
10987c478bd9Sstevel@tonic-gate 
10997c478bd9Sstevel@tonic-gate 	volatile uint64_t *iommu_ctl_p = iommu_p->iommu_ctrl_reg;
11007c478bd9Sstevel@tonic-gate 	volatile uint64_t tsb_bar_val = iommu_p->iommu_tsb_paddr;
11017c478bd9Sstevel@tonic-gate 	volatile uint64_t *tsb_bar_p = iommu_p->iommu_tsb_base_addr_reg;
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 	DEBUG2(DBG_ATTACH, iommu_p->iommu_pci_p->pci_dip,
11047c478bd9Sstevel@tonic-gate 		"\npci_iommu_config: pbm_csr_p=%016llx pbm_ctl=%016llx",
11057c478bd9Sstevel@tonic-gate 		pbm_csr_p, pbm_ctl);
11067c478bd9Sstevel@tonic-gate 	DEBUG2(DBG_ATTACH|DBG_CONT, iommu_p->iommu_pci_p->pci_dip,
11077c478bd9Sstevel@tonic-gate 		"\n\tiommu_ctl_p=%016llx iommu_ctl=%016llx",
11087c478bd9Sstevel@tonic-gate 		iommu_ctl_p, iommu_ctl);
11097c478bd9Sstevel@tonic-gate 	DEBUG2(DBG_ATTACH|DBG_CONT, iommu_p->iommu_pci_p->pci_dip,
11107c478bd9Sstevel@tonic-gate 		"\n\tcfgpa=%016llx tsb_bar_val=%016llx", cfgpa, tsb_bar_val);
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	if (!cfgpa)
11137c478bd9Sstevel@tonic-gate 		goto reprog;
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	/* disable PBM arbiters - turn off bits 0-7 */
11167c478bd9Sstevel@tonic-gate 	*pbm_csr_p = (pbm_ctl >> 8) << 8;
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 	/* make sure we own the bus by reading any child device config space */
11197c478bd9Sstevel@tonic-gate 	(void) ldphysio(cfgpa); /* also flushes the prev write */
11207c478bd9Sstevel@tonic-gate reprog:
11217c478bd9Sstevel@tonic-gate 	*tsb_bar_p = tsb_bar_val;
11227c478bd9Sstevel@tonic-gate 	*iommu_ctl_p = iommu_ctl;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	*pbm_csr_p = pbm_ctl;	/* re-enable bus arbitration */
11257c478bd9Sstevel@tonic-gate 	pbm_ctl = *pbm_csr_p;	/* flush all prev writes */
11267c478bd9Sstevel@tonic-gate }
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate int
pci_sc_ctx_inv(dev_info_t * dip,sc_t * sc_p,ddi_dma_impl_t * mp)11297c478bd9Sstevel@tonic-gate pci_sc_ctx_inv(dev_info_t *dip, sc_t *sc_p, ddi_dma_impl_t *mp)
11307c478bd9Sstevel@tonic-gate {
11317c478bd9Sstevel@tonic-gate 	ASSERT(0);
11327c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
11337c478bd9Sstevel@tonic-gate }
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate void
pci_cb_setup(pci_t * pci_p)11367c478bd9Sstevel@tonic-gate pci_cb_setup(pci_t *pci_p)
11377c478bd9Sstevel@tonic-gate {
11387c478bd9Sstevel@tonic-gate 	uint64_t csr, csr_pa, pa;
11397c478bd9Sstevel@tonic-gate 	cb_t *cb_p = pci_p->pci_cb_p;
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	/* cb_p->cb_node_id = 0; */
11427c478bd9Sstevel@tonic-gate 	cb_p->cb_ign = PCI_ID_TO_IGN(pci_p->pci_id);
11437c478bd9Sstevel@tonic-gate 	pa = (uint64_t)hat_getpfnum(kas.a_hat, pci_p->pci_address[0]);
11447c478bd9Sstevel@tonic-gate 	cb_p->cb_base_pa  = pa = pa >> (32 - MMU_PAGESHIFT) << 32;
11457c478bd9Sstevel@tonic-gate 	cb_p->cb_map_pa = pa + PSYCHO_IB_OBIO_INTR_MAP_REG_OFFSET;
11467c478bd9Sstevel@tonic-gate 	cb_p->cb_clr_pa = pa + PSYCHO_IB_OBIO_CLEAR_INTR_REG_OFFSET;
11477c478bd9Sstevel@tonic-gate 	cb_p->cb_obsta_pa = pa + COMMON_IB_OBIO_INTR_STATE_DIAG_REG;
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 	csr_pa = pa + PSYCHO_CB_CONTROL_STATUS_REG_OFFSET;
11507c478bd9Sstevel@tonic-gate 	csr = lddphysio(csr_pa);
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 	/*
11537c478bd9Sstevel@tonic-gate 	 * Clear any pending address parity errors.
11547c478bd9Sstevel@tonic-gate 	 */
11557c478bd9Sstevel@tonic-gate 	if (csr & COMMON_CB_CONTROL_STATUS_APERR) {
11567c478bd9Sstevel@tonic-gate 		csr |= COMMON_CB_CONTROL_STATUS_APERR;
11577c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "clearing UPA address parity error\n");
11587c478bd9Sstevel@tonic-gate 	}
11597c478bd9Sstevel@tonic-gate 	csr |= COMMON_CB_CONTROL_STATUS_APCKEN;
11607c478bd9Sstevel@tonic-gate 	csr &= ~COMMON_CB_CONTROL_STATUS_IAP;
11617c478bd9Sstevel@tonic-gate 	stdphysio(csr_pa, csr);
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate #ifdef _STARFIRE
11647c478bd9Sstevel@tonic-gate 	/* Setup Starfire interrupt target translation */
11657c478bd9Sstevel@tonic-gate 	pc_ittrans_init(pci_p->pci_id, &cb_p->cb_ittrans_cookie);
11667c478bd9Sstevel@tonic-gate #endif /* _STARFIRE */
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate }
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate void
pci_ecc_setup(ecc_t * ecc_p)11717c478bd9Sstevel@tonic-gate pci_ecc_setup(ecc_t *ecc_p)
11727c478bd9Sstevel@tonic-gate {
11737c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ue.ecc_errpndg_mask = 0;
11747c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ue.ecc_offset_mask = PSYCHO_ECC_UE_AFSR_DW_OFFSET;
11757c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ue.ecc_offset_shift = PSYCHO_ECC_UE_AFSR_DW_OFFSET_SHIFT;
11767c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ue.ecc_size_log2 = 3;
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ce.ecc_errpndg_mask = 0;
11797c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ce.ecc_offset_mask = PSYCHO_ECC_CE_AFSR_DW_OFFSET;
11807c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ce.ecc_offset_shift = PSYCHO_ECC_CE_AFSR_DW_OFFSET_SHIFT;
11817c478bd9Sstevel@tonic-gate 	ecc_p->ecc_ce.ecc_size_log2 = 3;
11827c478bd9Sstevel@tonic-gate }
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate /*
11857c478bd9Sstevel@tonic-gate  * overwrite dvma end address (only on virtual-dma systems)
11867c478bd9Sstevel@tonic-gate  * initialize tsb size
11877c478bd9Sstevel@tonic-gate  * reset context bits
11887c478bd9Sstevel@tonic-gate  * return: IOMMU CSR bank base address (VA)
11897c478bd9Sstevel@tonic-gate  */
11907c478bd9Sstevel@tonic-gate uintptr_t
pci_iommu_setup(iommu_t * iommu_p)11917c478bd9Sstevel@tonic-gate pci_iommu_setup(iommu_t *iommu_p)
11927c478bd9Sstevel@tonic-gate {
11937c478bd9Sstevel@tonic-gate 	pci_dvma_range_prop_t *dvma_prop;
11947c478bd9Sstevel@tonic-gate 	int dvma_prop_len;
11957c478bd9Sstevel@tonic-gate 
11967c478bd9Sstevel@tonic-gate 	pci_t *pci_p = iommu_p->iommu_pci_p;
11977c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pci_p->pci_dip;
11987c478bd9Sstevel@tonic-gate 	uint_t tsb_size = iommu_tsb_cookie_to_size(pci_p->pci_tsb_cookie);
11997c478bd9Sstevel@tonic-gate 	uint_t tsb_size_prop;
12007c478bd9Sstevel@tonic-gate 
12017c478bd9Sstevel@tonic-gate 	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
12027c478bd9Sstevel@tonic-gate 		"virtual-dma", (caddr_t)&dvma_prop, &dvma_prop_len) !=
12037c478bd9Sstevel@tonic-gate 		DDI_PROP_SUCCESS)
12047c478bd9Sstevel@tonic-gate 		goto tsb_done;
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate 	if (dvma_prop_len != sizeof (pci_dvma_range_prop_t)) {
12077c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s%d: invalid virtual-dma property",
12087c478bd9Sstevel@tonic-gate 			ddi_driver_name(dip), ddi_get_instance(dip));
12097c478bd9Sstevel@tonic-gate 		goto tsb_end;
12107c478bd9Sstevel@tonic-gate 	}
12117c478bd9Sstevel@tonic-gate 	iommu_p->iommu_dvma_end = dvma_prop->dvma_base +
12127c478bd9Sstevel@tonic-gate 		(dvma_prop->dvma_len - 1);
12137c478bd9Sstevel@tonic-gate 	tsb_size_prop = IOMMU_BTOP(dvma_prop->dvma_len) * sizeof (uint64_t);
12147c478bd9Sstevel@tonic-gate 	tsb_size = MIN(tsb_size_prop, tsb_size);
12157c478bd9Sstevel@tonic-gate tsb_end:
12167c478bd9Sstevel@tonic-gate 	kmem_free(dvma_prop, dvma_prop_len);
12177c478bd9Sstevel@tonic-gate tsb_done:
12187c478bd9Sstevel@tonic-gate 	iommu_p->iommu_tsb_size = iommu_tsb_size_encode(tsb_size);
12197c478bd9Sstevel@tonic-gate 
12207c478bd9Sstevel@tonic-gate 	if (CHIP_TYPE(pci_p) != PCI_CHIP_HUMMINGBIRD)
12217c478bd9Sstevel@tonic-gate 		pci_preserve_iommu_tsb = 0;
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 	/*
12247c478bd9Sstevel@tonic-gate 	 * Psycho has no context support.
12257c478bd9Sstevel@tonic-gate 	 */
12267c478bd9Sstevel@tonic-gate 	iommu_p->iommu_ctx_bitmap = NULL;
12277c478bd9Sstevel@tonic-gate 	iommu_p->iommu_flush_ctx_reg = NULL;
12287c478bd9Sstevel@tonic-gate 	pci_use_contexts = 0;
12297c478bd9Sstevel@tonic-gate 	pci_sc_use_contexts = 0;
12307c478bd9Sstevel@tonic-gate 
12317c478bd9Sstevel@tonic-gate 	/*
12327c478bd9Sstevel@tonic-gate 	 * Determine the virtual address of the register block
12337c478bd9Sstevel@tonic-gate 	 * containing the iommu control registers.
12347c478bd9Sstevel@tonic-gate 	 */
12357c478bd9Sstevel@tonic-gate 	return (get_reg_base(pci_p));
12367c478bd9Sstevel@tonic-gate }
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12397c478bd9Sstevel@tonic-gate void
pci_iommu_teardown(iommu_t * iommu_p)12407c478bd9Sstevel@tonic-gate pci_iommu_teardown(iommu_t *iommu_p)
12417c478bd9Sstevel@tonic-gate {
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate /* The psycho+ PBM reg base is at 1fe.0000.2000 */
12457c478bd9Sstevel@tonic-gate uintptr_t
get_pbm_reg_base(pci_t * pci_p)12467c478bd9Sstevel@tonic-gate get_pbm_reg_base(pci_t *pci_p)
12477c478bd9Sstevel@tonic-gate {
12487c478bd9Sstevel@tonic-gate 	return ((uintptr_t)(pci_p->pci_address[0] +
12497c478bd9Sstevel@tonic-gate 		(pci_stream_buf_exists ? 0 : PSYCHO_PCI_PBM_REG_BASE)));
12507c478bd9Sstevel@tonic-gate }
12517c478bd9Sstevel@tonic-gate 
12527c478bd9Sstevel@tonic-gate void
pci_post_uninit_child(pci_t * pci_p)12537c478bd9Sstevel@tonic-gate pci_post_uninit_child(pci_t *pci_p)
12547c478bd9Sstevel@tonic-gate {
12557c478bd9Sstevel@tonic-gate }
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate void
pci_pbm_setup(pbm_t * pbm_p)12587c478bd9Sstevel@tonic-gate pci_pbm_setup(pbm_t *pbm_p)
12597c478bd9Sstevel@tonic-gate {
12607c478bd9Sstevel@tonic-gate 	pci_t *pci_p = pbm_p->pbm_pci_p;
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 	/*
12637c478bd9Sstevel@tonic-gate 	 * Get the base virtual address for the PBM control block.
12647c478bd9Sstevel@tonic-gate 	 */
12657c478bd9Sstevel@tonic-gate 	uintptr_t a = get_pbm_reg_base(pci_p);
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate 	/*
12687c478bd9Sstevel@tonic-gate 	 * Get the virtual address of the PCI configuration header.
12697c478bd9Sstevel@tonic-gate 	 * This should be mapped little-endian.
12707c478bd9Sstevel@tonic-gate 	 */
12717c478bd9Sstevel@tonic-gate 	pbm_p->pbm_config_header =
12727c478bd9Sstevel@tonic-gate 		(config_header_t *)get_config_reg_base(pci_p);
12737c478bd9Sstevel@tonic-gate 
12747c478bd9Sstevel@tonic-gate 	/*
12757c478bd9Sstevel@tonic-gate 	 * Get the virtual addresses for control, error and diag
12767c478bd9Sstevel@tonic-gate 	 * registers.
12777c478bd9Sstevel@tonic-gate 	 */
12787c478bd9Sstevel@tonic-gate 	pbm_p->pbm_ctrl_reg = (uint64_t *)(a + PSYCHO_PCI_CTRL_REG_OFFSET);
12797c478bd9Sstevel@tonic-gate 	pbm_p->pbm_diag_reg = (uint64_t *)(a + PSYCHO_PCI_DIAG_REG_OFFSET);
12807c478bd9Sstevel@tonic-gate 	pbm_p->pbm_async_flt_status_reg =
12817c478bd9Sstevel@tonic-gate 		(uint64_t *)(a + PSYCHO_PCI_ASYNC_FLT_STATUS_REG_OFFSET);
12827c478bd9Sstevel@tonic-gate 	pbm_p->pbm_async_flt_addr_reg =
12837c478bd9Sstevel@tonic-gate 		(uint64_t *)(a + PSYCHO_PCI_ASYNC_FLT_ADDR_REG_OFFSET);
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate 	if (CHIP_TYPE(pci_p) >= PCI_CHIP_SABRE)
12867c478bd9Sstevel@tonic-gate 		pbm_p->pbm_sync_reg_pa =
12877c478bd9Sstevel@tonic-gate 			pci_p->pci_cb_p->cb_base_pa + DMA_WRITE_SYNC_REG;
12887c478bd9Sstevel@tonic-gate }
12897c478bd9Sstevel@tonic-gate 
12907c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12917c478bd9Sstevel@tonic-gate void
pci_pbm_teardown(pbm_t * pbm_p)12927c478bd9Sstevel@tonic-gate pci_pbm_teardown(pbm_t *pbm_p)
12937c478bd9Sstevel@tonic-gate {
12947c478bd9Sstevel@tonic-gate }
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate void
pci_sc_setup(sc_t * sc_p)12977c478bd9Sstevel@tonic-gate pci_sc_setup(sc_t *sc_p)
12987c478bd9Sstevel@tonic-gate {
12997c478bd9Sstevel@tonic-gate 	pci_t *pci_p = sc_p->sc_pci_p;
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 	/*
13027c478bd9Sstevel@tonic-gate 	 * Determine the virtual addresses of the streaming cache
13037c478bd9Sstevel@tonic-gate 	 * control/status and flush registers.
13047c478bd9Sstevel@tonic-gate 	 */
13057c478bd9Sstevel@tonic-gate 	uintptr_t a = get_pbm_reg_base(pci_p);
13067c478bd9Sstevel@tonic-gate 	sc_p->sc_ctrl_reg = (uint64_t *)(a + PSYCHO_SC_CTRL_REG_OFFSET);
13077c478bd9Sstevel@tonic-gate 	sc_p->sc_invl_reg = (uint64_t *)(a + PSYCHO_SC_INVL_REG_OFFSET);
13087c478bd9Sstevel@tonic-gate 	sc_p->sc_sync_reg = (uint64_t *)(a + PSYCHO_SC_SYNC_REG_OFFSET);
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 	/*
13117c478bd9Sstevel@tonic-gate 	 * Determine the virtual addresses of the streaming cache
13127c478bd9Sstevel@tonic-gate 	 * diagnostic access registers.
13137c478bd9Sstevel@tonic-gate 	 */
13147c478bd9Sstevel@tonic-gate 	a = get_reg_base(pci_p);
13157c478bd9Sstevel@tonic-gate 	if (pci_p->pci_bus_range.lo != 0) {
13167c478bd9Sstevel@tonic-gate 		sc_p->sc_data_diag_acc = (uint64_t *)
13177c478bd9Sstevel@tonic-gate 				(a + PSYCHO_SC_A_DATA_DIAG_OFFSET);
13187c478bd9Sstevel@tonic-gate 		sc_p->sc_tag_diag_acc = (uint64_t *)
13197c478bd9Sstevel@tonic-gate 				(a + PSYCHO_SC_A_TAG_DIAG_OFFSET);
13207c478bd9Sstevel@tonic-gate 		sc_p->sc_ltag_diag_acc = (uint64_t *)
13217c478bd9Sstevel@tonic-gate 				(a + PSYCHO_SC_A_LTAG_DIAG_OFFSET);
13227c478bd9Sstevel@tonic-gate 	} else {
13237c478bd9Sstevel@tonic-gate 		sc_p->sc_data_diag_acc = (uint64_t *)
13247c478bd9Sstevel@tonic-gate 				(a + PSYCHO_SC_B_DATA_DIAG_OFFSET);
13257c478bd9Sstevel@tonic-gate 		sc_p->sc_tag_diag_acc = (uint64_t *)
13267c478bd9Sstevel@tonic-gate 				(a + PSYCHO_SC_B_TAG_DIAG_OFFSET);
13277c478bd9Sstevel@tonic-gate 		sc_p->sc_ltag_diag_acc = (uint64_t *)
13287c478bd9Sstevel@tonic-gate 				(a + PSYCHO_SC_B_LTAG_DIAG_OFFSET);
13297c478bd9Sstevel@tonic-gate 	}
13307c478bd9Sstevel@tonic-gate }
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate int
pci_get_numproxy(dev_info_t * dip)13337c478bd9Sstevel@tonic-gate pci_get_numproxy(dev_info_t *dip)
13347c478bd9Sstevel@tonic-gate {
13357c478bd9Sstevel@tonic-gate 	return (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
13367c478bd9Sstevel@tonic-gate 		"#upa-interrupt-proxies", 1));
13377c478bd9Sstevel@tonic-gate }
13387c478bd9Sstevel@tonic-gate 
13397c478bd9Sstevel@tonic-gate int
pci_get_portid(dev_info_t * dip)13407c478bd9Sstevel@tonic-gate pci_get_portid(dev_info_t *dip)
13417c478bd9Sstevel@tonic-gate {
13427c478bd9Sstevel@tonic-gate 	return (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
13437c478bd9Sstevel@tonic-gate 	    "upa-portid", -1));
13447c478bd9Sstevel@tonic-gate }
13457c478bd9Sstevel@tonic-gate 
13467c478bd9Sstevel@tonic-gate /*
13477c478bd9Sstevel@tonic-gate  * pbm_has_pass_1_cheerio
13487c478bd9Sstevel@tonic-gate  *
13497c478bd9Sstevel@tonic-gate  *
13507c478bd9Sstevel@tonic-gate  * Given a PBM soft state pointer, this routine scans it child nodes
13517c478bd9Sstevel@tonic-gate  * to see if one is a pass 1 cheerio.
13527c478bd9Sstevel@tonic-gate  *
13537c478bd9Sstevel@tonic-gate  * return value: 1 if pass 1 cheerio is found, 0 otherwise
13547c478bd9Sstevel@tonic-gate  */
13557c478bd9Sstevel@tonic-gate static int
pbm_has_pass_1_cheerio(pci_t * pci_p)13567c478bd9Sstevel@tonic-gate pbm_has_pass_1_cheerio(pci_t *pci_p)
13577c478bd9Sstevel@tonic-gate {
13587c478bd9Sstevel@tonic-gate 	dev_info_t *cdip;
13597c478bd9Sstevel@tonic-gate 	int found = 0;
13607c478bd9Sstevel@tonic-gate 	char *s;
13617c478bd9Sstevel@tonic-gate 	int rev;
13627c478bd9Sstevel@tonic-gate 
13637c478bd9Sstevel@tonic-gate 	cdip = ddi_get_child(pci_p->pci_dip);
13647c478bd9Sstevel@tonic-gate 	while (cdip != NULL && found == 0) {
13657c478bd9Sstevel@tonic-gate 		s = ddi_get_name(cdip);
13667c478bd9Sstevel@tonic-gate 		if (strcmp(s, "ebus") == 0 || strcmp(s, "pci108e,1000") == 0) {
13677c478bd9Sstevel@tonic-gate 			rev =
13687c478bd9Sstevel@tonic-gate 			    ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
13697c478bd9Sstevel@tonic-gate 				"revision-id", 0);
13707c478bd9Sstevel@tonic-gate 			if (rev == 0)
13717c478bd9Sstevel@tonic-gate 				found = 1;
13727c478bd9Sstevel@tonic-gate 		}
13737c478bd9Sstevel@tonic-gate 		cdip = ddi_get_next_sibling(cdip);
13747c478bd9Sstevel@tonic-gate 	}
13757c478bd9Sstevel@tonic-gate 	return (found);
13767c478bd9Sstevel@tonic-gate }
13777c478bd9Sstevel@tonic-gate 
13787c478bd9Sstevel@tonic-gate /*
13797c478bd9Sstevel@tonic-gate  * Psycho Performance Events.
13807c478bd9Sstevel@tonic-gate  */
13817c478bd9Sstevel@tonic-gate pci_kev_mask_t
13827c478bd9Sstevel@tonic-gate psycho_pci_events[] = {
13837c478bd9Sstevel@tonic-gate 	{"dvma_stream_rd_a", 0x0},	{"dvma_stream_wr_a", 0x1},
13847c478bd9Sstevel@tonic-gate 	{"dvma_const_rd_a", 0x2},	{"dvma_const_wr_a", 0x3},
13857c478bd9Sstevel@tonic-gate 	{"dvma_stream_buf_mis_a", 0x4}, {"dvma_cycles_a", 0x5},
13867c478bd9Sstevel@tonic-gate 	{"dvma_wd_xfr_a", 0x6},		{"pio_cycles_a", 0x7},
13877c478bd9Sstevel@tonic-gate 	{"dvma_stream_rd_b", 0x8},	{"dvma_stream_wr_b", 0x9},
13887c478bd9Sstevel@tonic-gate 	{"dvma_const_rd_b", 0xa},	{"dvma_const_wr_b", 0xb},
13897c478bd9Sstevel@tonic-gate 	{"dvma_stream_buf_mis_b", 0xc}, {"dvma_cycles_b", 0xd},
13907c478bd9Sstevel@tonic-gate 	{"dvma_wd_xfr_b", 0xe},		{"pio_cycles_b", 0xf},
13917c478bd9Sstevel@tonic-gate 	{"dvma_tlb_misses", 0x10},	{"interrupts", 0x11},
13927c478bd9Sstevel@tonic-gate 	{"upa_inter_nack", 0x12},	{"pio_reads", 0x13},
13937c478bd9Sstevel@tonic-gate 	{"pio_writes", 0x14},		{"merge_buffer", 0x15},
13947c478bd9Sstevel@tonic-gate 	{"dma_tbwalk_a", 0x16},		{"dma_stc_a", 0x17},
13957c478bd9Sstevel@tonic-gate 	{"dma_tbwalk_b", 0x18},		{"dma_stc_b", 0x19},
13967c478bd9Sstevel@tonic-gate 	{"clear_pic", 0x1f}
13977c478bd9Sstevel@tonic-gate };
13987c478bd9Sstevel@tonic-gate 
13997c478bd9Sstevel@tonic-gate /*
14007c478bd9Sstevel@tonic-gate  * Create the picN kstat's.
14017c478bd9Sstevel@tonic-gate  */
14027c478bd9Sstevel@tonic-gate void
pci_kstat_init()14037c478bd9Sstevel@tonic-gate pci_kstat_init()
14047c478bd9Sstevel@tonic-gate {
14057c478bd9Sstevel@tonic-gate 	pci_name_kstat = (pci_ksinfo_t *)kmem_alloc(sizeof (pci_ksinfo_t),
14067c478bd9Sstevel@tonic-gate 		KM_NOSLEEP);
14077c478bd9Sstevel@tonic-gate 
14087c478bd9Sstevel@tonic-gate 	if (pci_name_kstat == NULL) {
14097c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "pcipsy : no space for kstat\n");
14107c478bd9Sstevel@tonic-gate 	} else {
14117c478bd9Sstevel@tonic-gate 		pci_name_kstat->pic_no_evs =
14127c478bd9Sstevel@tonic-gate 			sizeof (psycho_pci_events) / sizeof (pci_kev_mask_t);
14137c478bd9Sstevel@tonic-gate 		pci_name_kstat->pic_shift[0] = PSYCHO_SHIFT_PIC0;
14147c478bd9Sstevel@tonic-gate 		pci_name_kstat->pic_shift[1] = PSYCHO_SHIFT_PIC1;
14157c478bd9Sstevel@tonic-gate 		pci_create_name_kstat("pcip",
14167c478bd9Sstevel@tonic-gate 			pci_name_kstat, psycho_pci_events);
14177c478bd9Sstevel@tonic-gate 	}
14187c478bd9Sstevel@tonic-gate }
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate /*
14217c478bd9Sstevel@tonic-gate  * Called from _fini()
14227c478bd9Sstevel@tonic-gate  */
14237c478bd9Sstevel@tonic-gate void
pci_kstat_fini()14247c478bd9Sstevel@tonic-gate pci_kstat_fini()
14257c478bd9Sstevel@tonic-gate {
14267c478bd9Sstevel@tonic-gate 	if (pci_name_kstat != NULL) {
14277c478bd9Sstevel@tonic-gate 		pci_delete_name_kstat(pci_name_kstat);
14287c478bd9Sstevel@tonic-gate 		kmem_free(pci_name_kstat, sizeof (pci_ksinfo_t));
14297c478bd9Sstevel@tonic-gate 		pci_name_kstat = NULL;
14307c478bd9Sstevel@tonic-gate 	}
14317c478bd9Sstevel@tonic-gate }
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate /* ARGSUSED */
14347c478bd9Sstevel@tonic-gate void
pci_add_pci_kstat(pci_t * pci_p)14357c478bd9Sstevel@tonic-gate pci_add_pci_kstat(pci_t *pci_p)
14367c478bd9Sstevel@tonic-gate {
14377c478bd9Sstevel@tonic-gate }
14387c478bd9Sstevel@tonic-gate 
14397c478bd9Sstevel@tonic-gate /* ARGSUSED */
14407c478bd9Sstevel@tonic-gate void
pci_rem_pci_kstat(pci_t * pci_p)14417c478bd9Sstevel@tonic-gate pci_rem_pci_kstat(pci_t *pci_p)
14427c478bd9Sstevel@tonic-gate {
14437c478bd9Sstevel@tonic-gate }
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate /*
14467c478bd9Sstevel@tonic-gate  * Create the performance 'counters' kstat.
14477c478bd9Sstevel@tonic-gate  */
14487c478bd9Sstevel@tonic-gate void
pci_add_upstream_kstat(pci_t * pci_p)14497c478bd9Sstevel@tonic-gate pci_add_upstream_kstat(pci_t *pci_p)
14507c478bd9Sstevel@tonic-gate {
14517c478bd9Sstevel@tonic-gate 	pci_common_t 	*cmn_p = pci_p->pci_common_p;
14527c478bd9Sstevel@tonic-gate 	pci_cntr_pa_t	*cntr_pa_p = &cmn_p->pci_cmn_uks_pa;
14537c478bd9Sstevel@tonic-gate 	uint64_t regbase = va_to_pa((void *)get_reg_base(pci_p));
14547c478bd9Sstevel@tonic-gate 
14557c478bd9Sstevel@tonic-gate 	cntr_pa_p->pcr_pa = regbase + PSYCHO_PERF_PCR_OFFSET;
14567c478bd9Sstevel@tonic-gate 	cntr_pa_p->pic_pa = regbase + PSYCHO_PERF_PIC_OFFSET;
14577c478bd9Sstevel@tonic-gate 	cmn_p->pci_common_uksp = pci_create_cntr_kstat(pci_p, "pcip",
14587c478bd9Sstevel@tonic-gate 		NUM_OF_PICS, pci_cntr_kstat_pa_update, cntr_pa_p);
14597c478bd9Sstevel@tonic-gate }
14607c478bd9Sstevel@tonic-gate 
14617c478bd9Sstevel@tonic-gate /*
14627c478bd9Sstevel@tonic-gate  * Extract the drivers binding name to identify which chip
14637c478bd9Sstevel@tonic-gate  * we're binding to.  Whenever a new bus bridge is created, the driver alias
14647c478bd9Sstevel@tonic-gate  * entry should be added here to identify the device if needed.  If a device
14657c478bd9Sstevel@tonic-gate  * isn't added, the identity defaults to PCI_CHIP_UNIDENTIFIED.
14667c478bd9Sstevel@tonic-gate  */
14677c478bd9Sstevel@tonic-gate static uint32_t
pci_identity_init(pci_t * pci_p)14687c478bd9Sstevel@tonic-gate pci_identity_init(pci_t *pci_p)
14697c478bd9Sstevel@tonic-gate {
14707c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pci_p->pci_dip;
14717c478bd9Sstevel@tonic-gate 	char *name = ddi_binding_name(dip);
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate 	if (strcmp(name, "pci108e,8000") == 0)
14747c478bd9Sstevel@tonic-gate 		return (CHIP_ID(PCI_CHIP_PSYCHO, 0x00, 0x00));
14757c478bd9Sstevel@tonic-gate 	if (strcmp(name, "pci108e,a000") == 0)
14767c478bd9Sstevel@tonic-gate 		return (CHIP_ID(PCI_CHIP_SABRE, 0x00, 0x00));
14777c478bd9Sstevel@tonic-gate 	if (strcmp(name, "pci108e,a001") == 0)
14787c478bd9Sstevel@tonic-gate 		return (CHIP_ID(PCI_CHIP_HUMMINGBIRD, 0x00, 0x00));
14797c478bd9Sstevel@tonic-gate 	cmn_err(CE_CONT, "?%s%d:using default chip identity\n",
14807c478bd9Sstevel@tonic-gate 		ddi_driver_name(dip), ddi_get_instance(dip));
14817c478bd9Sstevel@tonic-gate 	return (CHIP_ID(PCI_CHIP_PSYCHO, 0x00, 0x00));
14827c478bd9Sstevel@tonic-gate }
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14857c478bd9Sstevel@tonic-gate void
pci_post_init_child(pci_t * pci_p,dev_info_t * child)14867c478bd9Sstevel@tonic-gate pci_post_init_child(pci_t *pci_p, dev_info_t *child)
14877c478bd9Sstevel@tonic-gate {
14887c478bd9Sstevel@tonic-gate }
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14917c478bd9Sstevel@tonic-gate int
pci_pbm_add_intr(pci_t * pci_p)14927c478bd9Sstevel@tonic-gate pci_pbm_add_intr(pci_t *pci_p)
14937c478bd9Sstevel@tonic-gate {
14947c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
14957c478bd9Sstevel@tonic-gate }
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14987c478bd9Sstevel@tonic-gate void
pci_pbm_rem_intr(pci_t * pci_p)14997c478bd9Sstevel@tonic-gate pci_pbm_rem_intr(pci_t *pci_p)
15007c478bd9Sstevel@tonic-gate {
15017c478bd9Sstevel@tonic-gate }
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15047c478bd9Sstevel@tonic-gate void
pci_pbm_suspend(pci_t * pci_p)15057c478bd9Sstevel@tonic-gate pci_pbm_suspend(pci_t *pci_p)
15067c478bd9Sstevel@tonic-gate {
15077c478bd9Sstevel@tonic-gate }
15087c478bd9Sstevel@tonic-gate 
15097c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15107c478bd9Sstevel@tonic-gate void
pci_pbm_resume(pci_t * pci_p)15117c478bd9Sstevel@tonic-gate pci_pbm_resume(pci_t *pci_p)
15127c478bd9Sstevel@tonic-gate {
15137c478bd9Sstevel@tonic-gate }
15147c478bd9Sstevel@tonic-gate 
15157c478bd9Sstevel@tonic-gate /*
15167c478bd9Sstevel@tonic-gate  * pcipsy error handling 101:
15177c478bd9Sstevel@tonic-gate  *
15187c478bd9Sstevel@tonic-gate  * The various functions below are responsible for error handling. Given
15197c478bd9Sstevel@tonic-gate  * a particular error, they must gather the appropriate state, report all
15207c478bd9Sstevel@tonic-gate  * errors with correct payload, and attempt recovery where ever possible.
15217c478bd9Sstevel@tonic-gate  *
15227c478bd9Sstevel@tonic-gate  * Recovery in the context of this driver is being able notify a leaf device
15237c478bd9Sstevel@tonic-gate  * of the failed transaction. This leaf device may either be the master or
15247c478bd9Sstevel@tonic-gate  * target for this transaction and may have already received an error
15257c478bd9Sstevel@tonic-gate  * notification via a PCI interrupt. Notification is done via DMA and access
15267c478bd9Sstevel@tonic-gate  * handles. If we capture an address for the transaction then we can map it
15277c478bd9Sstevel@tonic-gate  * to a handle(if the leaf device is fma-compliant) and fault the handle as
15287c478bd9Sstevel@tonic-gate  * well as call the device driver registered callback.
15297c478bd9Sstevel@tonic-gate  *
15307c478bd9Sstevel@tonic-gate  * The hardware can either interrupt or trap upon detection of an error, in
15317c478bd9Sstevel@tonic-gate  * some rare cases it also causes a fatal reset.
15327c478bd9Sstevel@tonic-gate  *
15337c478bd9Sstevel@tonic-gate  * pbm_error_intr() and ecc_intr() are responsible for PCI Block Module
15347c478bd9Sstevel@tonic-gate  * errors(generic PCI + bridge specific) and ECC errors, respectively. They
15357c478bd9Sstevel@tonic-gate  * are common between pcisch and pcipsy and therefore exist in pci_pbm.c and
15367c478bd9Sstevel@tonic-gate  * pci_ecc.c. To support error handling certain chip specific handlers
15377c478bd9Sstevel@tonic-gate  * must exist and they are defined below.
15387c478bd9Sstevel@tonic-gate  *
15397c478bd9Sstevel@tonic-gate  * cpu_deferred_error() and cpu_async_error(), handle the traps that may
15407c478bd9Sstevel@tonic-gate  * have originated from IO space. They call into the registered IO callbacks
15417c478bd9Sstevel@tonic-gate  * to report and handle errors that may have caused the trap.
15427c478bd9Sstevel@tonic-gate  *
15437c478bd9Sstevel@tonic-gate  * pci_pbm_err_handler() is called by pbm_error_intr() or pci_err_callback()
15447c478bd9Sstevel@tonic-gate  * (generic fma callback for pcipsy/pcisch, pci_fm.c). pci_err_callback() is
15457c478bd9Sstevel@tonic-gate  * called when the CPU has trapped because of a possible IO error(TO/BERR/UE).
15467c478bd9Sstevel@tonic-gate  * It will call pci_pbm_err_handler() to report and handle all PCI/PBM/IOMMU
15477c478bd9Sstevel@tonic-gate  * related errors which are detected by the chip.
15487c478bd9Sstevel@tonic-gate  *
15497c478bd9Sstevel@tonic-gate  * pci_pbm_err_handler() calls a generic interface pbm_afsr_report()(pci_pbm.c)
15507c478bd9Sstevel@tonic-gate  * to report the pbm specific errors and attempt to map the failed address
15517c478bd9Sstevel@tonic-gate  * (if captured) to a device instance. pbm_afsr_report() calls a chip specific
15527c478bd9Sstevel@tonic-gate  * interface to interpret the afsr bits pci_pbm_classify()(pcisch.c/pcipsy.c).
15537c478bd9Sstevel@tonic-gate  *
15547c478bd9Sstevel@tonic-gate  * ecc_err_handler()(pci_ecc.c) also calls a chip specific interface to
15557c478bd9Sstevel@tonic-gate  * interpret the afsr, pci_ecc_classify(). ecc_err_handler() also calls
15567c478bd9Sstevel@tonic-gate  * pci_pbm_err_handler() and ndi_fm_handler_dispatch() to log any related
15577c478bd9Sstevel@tonic-gate  * errors.
15587c478bd9Sstevel@tonic-gate  *
15597c478bd9Sstevel@tonic-gate  * To make sure that the trap code and the interrupt code are not going
15607c478bd9Sstevel@tonic-gate  * to step on each others toes we have a per chip pci_fm_mutex. This also
15617c478bd9Sstevel@tonic-gate  * makes it necessary for us to be cautious while we are at a high PIL, so
15627c478bd9Sstevel@tonic-gate  * that we do not cause a subsequent trap that causes us to hang.
15637c478bd9Sstevel@tonic-gate  *
15647c478bd9Sstevel@tonic-gate  * The attempt to commonize code was meant to keep in line with the current
15657c478bd9Sstevel@tonic-gate  * pci driver implementation and it was not meant to confuse. If you are
15667c478bd9Sstevel@tonic-gate  * confused then don't worry, I was too.
15677c478bd9Sstevel@tonic-gate  */
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate /*
15707c478bd9Sstevel@tonic-gate  * For Psycho, a UE is always fatal, except if it is a translation error on a
15717c478bd9Sstevel@tonic-gate  * Darwin platform.  We ignore these because they do not cause data corruption.
15727c478bd9Sstevel@tonic-gate  */
15737c478bd9Sstevel@tonic-gate int
ecc_ue_is_fatal(struct async_flt * ecc)15747c478bd9Sstevel@tonic-gate ecc_ue_is_fatal(struct async_flt *ecc)
15757c478bd9Sstevel@tonic-gate {
15767c478bd9Sstevel@tonic-gate 	return (((uint_t)(ecc->flt_stat >> SABRE_UE_AFSR_PDTE_SHIFT) &
15777c478bd9Sstevel@tonic-gate 	    SABRE_UE_AFSR_E_PDTE) == 0);
15787c478bd9Sstevel@tonic-gate }
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate /*
15817c478bd9Sstevel@tonic-gate  * pci_ecc_classify, called by ecc_handler to classify ecc errors
15827c478bd9Sstevel@tonic-gate  * and determine if we should panic or not.
1583a1ca9cb8Sarutz  *
1584a1ca9cb8Sarutz  * Note that it is possible yet extremely rare for more than one
1585a1ca9cb8Sarutz  * primary error bit to be set.  We classify the ecc error based
1586a1ca9cb8Sarutz  * on the first set bit that is found.
15877c478bd9Sstevel@tonic-gate  */
15887c478bd9Sstevel@tonic-gate void
pci_ecc_classify(uint64_t err,ecc_errstate_t * ecc_err_p)15897c478bd9Sstevel@tonic-gate pci_ecc_classify(uint64_t err, ecc_errstate_t *ecc_err_p)
15907c478bd9Sstevel@tonic-gate {
15917c478bd9Sstevel@tonic-gate 	struct async_flt *ecc = &ecc_err_p->ecc_aflt;
15927c478bd9Sstevel@tonic-gate 	pci_common_t *cmn_p = ecc_err_p->ecc_ii_p.ecc_p->ecc_pci_cmn_p;
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cmn_p->pci_fm_mutex));
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate 	ecc_err_p->ecc_bridge_type = PCI_BRIDGE_TYPE(cmn_p);
15977c478bd9Sstevel@tonic-gate 	/*
15987c478bd9Sstevel@tonic-gate 	 * Get the parent bus id that caused the error.
15997c478bd9Sstevel@tonic-gate 	 */
16007c478bd9Sstevel@tonic-gate 	ecc_err_p->ecc_dev_id = (ecc_err_p->ecc_afsr & PSYCHO_ECC_UE_AFSR_ID)
16017c478bd9Sstevel@tonic-gate 			>> PSYCHO_ECC_UE_AFSR_ID_SHIFT;
16027c478bd9Sstevel@tonic-gate 	/*
16037c478bd9Sstevel@tonic-gate 	 * Determine the doubleword offset of the error.
16047c478bd9Sstevel@tonic-gate 	 */
16057c478bd9Sstevel@tonic-gate 	ecc_err_p->ecc_dw_offset = (ecc_err_p->ecc_afsr &
16067c478bd9Sstevel@tonic-gate 			PSYCHO_ECC_UE_AFSR_DW_OFFSET)
16077c478bd9Sstevel@tonic-gate 			>> PSYCHO_ECC_UE_AFSR_DW_OFFSET_SHIFT;
16087c478bd9Sstevel@tonic-gate 	/*
16097c478bd9Sstevel@tonic-gate 	 * Determine the primary error type.
16107c478bd9Sstevel@tonic-gate 	 */
1611*39470729Skd93003 	if (err & COMMON_ECC_AFSR_E_PIO) {
16127c478bd9Sstevel@tonic-gate 		if (ecc_err_p->ecc_ii_p.ecc_type == CBNINTR_UE) {
16137c478bd9Sstevel@tonic-gate 			if (ecc_err_p->ecc_pri) {
16147c478bd9Sstevel@tonic-gate 				ecc->flt_erpt_class = PCI_ECC_PIO_UE;
16157c478bd9Sstevel@tonic-gate 			} else {
16167c478bd9Sstevel@tonic-gate 				ecc->flt_erpt_class = PCI_ECC_SEC_PIO_UE;
16177c478bd9Sstevel@tonic-gate 			}
16187c478bd9Sstevel@tonic-gate 			ecc->flt_panic = ecc_ue_is_fatal(&ecc_err_p->ecc_aflt);
16197c478bd9Sstevel@tonic-gate 		} else {
16207c478bd9Sstevel@tonic-gate 			ecc->flt_erpt_class = ecc_err_p->ecc_pri ?
16217c478bd9Sstevel@tonic-gate 				PCI_ECC_PIO_CE : PCI_ECC_SEC_PIO_CE;
16227c478bd9Sstevel@tonic-gate 			return;
16237c478bd9Sstevel@tonic-gate 		}
1624*39470729Skd93003 	} else if (err & COMMON_ECC_AFSR_E_DRD) {
16257c478bd9Sstevel@tonic-gate 		if (ecc_err_p->ecc_ii_p.ecc_type == CBNINTR_UE) {
16267c478bd9Sstevel@tonic-gate 			if (ecc_err_p->ecc_pri) {
16277c478bd9Sstevel@tonic-gate 				ecc->flt_erpt_class = PCI_ECC_DRD_UE;
16287c478bd9Sstevel@tonic-gate 			} else {
16297c478bd9Sstevel@tonic-gate 				ecc->flt_erpt_class = PCI_ECC_SEC_DRD_UE;
16307c478bd9Sstevel@tonic-gate 			}
16317c478bd9Sstevel@tonic-gate 			ecc->flt_panic = ecc_ue_is_fatal(&ecc_err_p->ecc_aflt);
16327c478bd9Sstevel@tonic-gate 		} else {
16337c478bd9Sstevel@tonic-gate 			ecc->flt_erpt_class = ecc_err_p->ecc_pri ?
16347c478bd9Sstevel@tonic-gate 				PCI_ECC_DRD_CE : PCI_ECC_SEC_DRD_CE;
16357c478bd9Sstevel@tonic-gate 			return;
16367c478bd9Sstevel@tonic-gate 		}
1637*39470729Skd93003 	} else if (err & COMMON_ECC_AFSR_E_DWR) {
16387c478bd9Sstevel@tonic-gate 		if (ecc_err_p->ecc_ii_p.ecc_type == CBNINTR_UE) {
16397c478bd9Sstevel@tonic-gate 			if (ecc_err_p->ecc_pri) {
16407c478bd9Sstevel@tonic-gate 				ecc->flt_erpt_class = PCI_ECC_DWR_UE;
16417c478bd9Sstevel@tonic-gate 			} else {
16427c478bd9Sstevel@tonic-gate 				ecc->flt_erpt_class = PCI_ECC_SEC_DWR_UE;
16437c478bd9Sstevel@tonic-gate 			}
16447c478bd9Sstevel@tonic-gate 			ecc->flt_panic = ecc_ue_is_fatal(&ecc_err_p->ecc_aflt);
16457c478bd9Sstevel@tonic-gate 		} else {
16467c478bd9Sstevel@tonic-gate 			ecc->flt_erpt_class = ecc_err_p->ecc_pri ?
16477c478bd9Sstevel@tonic-gate 				PCI_ECC_DWR_CE : PCI_ECC_SEC_DWR_CE;
16487c478bd9Sstevel@tonic-gate 			return;
16497c478bd9Sstevel@tonic-gate 		}
16507c478bd9Sstevel@tonic-gate 	}
16517c478bd9Sstevel@tonic-gate }
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate ushort_t
pci_ecc_get_synd(uint64_t afsr)16547c478bd9Sstevel@tonic-gate pci_ecc_get_synd(uint64_t afsr)
16557c478bd9Sstevel@tonic-gate {
16567c478bd9Sstevel@tonic-gate 	return ((ushort_t)((afsr & PSYCHO_ECC_CE_AFSR_SYND)
16577c478bd9Sstevel@tonic-gate 		>> PSYCHO_ECC_CE_AFSR_SYND_SHIFT));
16587c478bd9Sstevel@tonic-gate }
16597c478bd9Sstevel@tonic-gate 
16607c478bd9Sstevel@tonic-gate /*
16617c478bd9Sstevel@tonic-gate  * pci_pbm_classify, called by pbm_afsr_report to classify piow afsr.
16627c478bd9Sstevel@tonic-gate  */
16637c478bd9Sstevel@tonic-gate int
pci_pbm_classify(pbm_errstate_t * pbm_err_p)16647c478bd9Sstevel@tonic-gate pci_pbm_classify(pbm_errstate_t *pbm_err_p)
16657c478bd9Sstevel@tonic-gate {
16667c478bd9Sstevel@tonic-gate 	uint32_t e;
16677c478bd9Sstevel@tonic-gate 	int nerr = 0;
16687c478bd9Sstevel@tonic-gate 	char **tmp_class;
16697c478bd9Sstevel@tonic-gate 
16707c478bd9Sstevel@tonic-gate 	if (pbm_err_p->pbm_pri) {
16717c478bd9Sstevel@tonic-gate 		tmp_class = &pbm_err_p->pbm_pci.pci_err_class;
16727c478bd9Sstevel@tonic-gate 		e = PBM_AFSR_TO_PRIERR(pbm_err_p->pbm_afsr);
16737c478bd9Sstevel@tonic-gate 		pbm_err_p->pbm_log = FM_LOG_PCI;
16747c478bd9Sstevel@tonic-gate 	} else {
16757c478bd9Sstevel@tonic-gate 		tmp_class = &pbm_err_p->pbm_err_class;
16767c478bd9Sstevel@tonic-gate 		e = PBM_AFSR_TO_SECERR(pbm_err_p->pbm_afsr);
16777c478bd9Sstevel@tonic-gate 		pbm_err_p->pbm_log = FM_LOG_PBM;
16787c478bd9Sstevel@tonic-gate 	}
16797c478bd9Sstevel@tonic-gate 
16807c478bd9Sstevel@tonic-gate 	if (e & PSYCHO_PCI_AFSR_E_MA) {
16817c478bd9Sstevel@tonic-gate 		*tmp_class = pbm_err_p->pbm_pri ? PCI_MA : PCI_SEC_MA;
16827c478bd9Sstevel@tonic-gate 		nerr++;
16837c478bd9Sstevel@tonic-gate 	}
16847c478bd9Sstevel@tonic-gate 	if (e & PSYCHO_PCI_AFSR_E_TA) {
16857c478bd9Sstevel@tonic-gate 		*tmp_class = pbm_err_p->pbm_pri ? PCI_REC_TA : PCI_SEC_REC_TA;
16867c478bd9Sstevel@tonic-gate 		nerr++;
16877c478bd9Sstevel@tonic-gate 	}
16887c478bd9Sstevel@tonic-gate 	if (e & PSYCHO_PCI_AFSR_E_RTRY) {
16897c478bd9Sstevel@tonic-gate 		pbm_err_p->pbm_err_class = pbm_err_p->pbm_pri ?
16907c478bd9Sstevel@tonic-gate 		    PCI_PBM_RETRY : PCI_SEC_PBM_RETRY;
16917c478bd9Sstevel@tonic-gate 		pbm_err_p->pbm_log = FM_LOG_PBM;
16927c478bd9Sstevel@tonic-gate 		nerr++;
16937c478bd9Sstevel@tonic-gate 	}
16947c478bd9Sstevel@tonic-gate 	if (e & PSYCHO_PCI_AFSR_E_PERR) {
16957c478bd9Sstevel@tonic-gate 		*tmp_class = pbm_err_p->pbm_pri ? PCI_MDPE : PCI_SEC_MDPE;
16967c478bd9Sstevel@tonic-gate 		nerr++;
16977c478bd9Sstevel@tonic-gate 	}
16987c478bd9Sstevel@tonic-gate 	return (nerr);
16997c478bd9Sstevel@tonic-gate }
17007c478bd9Sstevel@tonic-gate 
17017c478bd9Sstevel@tonic-gate /*
17027c478bd9Sstevel@tonic-gate  * Function used to clear PBM/PCI/IOMMU error state after error handling
17037c478bd9Sstevel@tonic-gate  * is complete. Only clearing error bits which have been logged. Called by
17047c478bd9Sstevel@tonic-gate  * pci_pbm_err_handler and pci_bus_exit.
17057c478bd9Sstevel@tonic-gate  */
17067c478bd9Sstevel@tonic-gate static void
pci_clear_error(pci_t * pci_p,pbm_errstate_t * pbm_err_p)17077c478bd9Sstevel@tonic-gate pci_clear_error(pci_t *pci_p, pbm_errstate_t *pbm_err_p)
17087c478bd9Sstevel@tonic-gate {
17097c478bd9Sstevel@tonic-gate 	pbm_t *pbm_p = pci_p->pci_pbm_p;
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pbm_p->pbm_pci_p->pci_common_p->pci_fm_mutex));
17127c478bd9Sstevel@tonic-gate 
17137c478bd9Sstevel@tonic-gate 	*pbm_p->pbm_ctrl_reg = pbm_err_p->pbm_ctl_stat;
17147c478bd9Sstevel@tonic-gate 	*pbm_p->pbm_async_flt_status_reg = pbm_err_p->pbm_afsr;
17157c478bd9Sstevel@tonic-gate 	pbm_p->pbm_config_header->ch_status_reg =
17167c478bd9Sstevel@tonic-gate 		pbm_err_p->pbm_pci.pci_cfg_stat;
17177c478bd9Sstevel@tonic-gate }
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate /*ARGSUSED*/
17207c478bd9Sstevel@tonic-gate int
pci_pbm_err_handler(dev_info_t * dip,ddi_fm_error_t * derr,const void * impl_data,int caller)17217c478bd9Sstevel@tonic-gate pci_pbm_err_handler(dev_info_t *dip, ddi_fm_error_t *derr,
17227c478bd9Sstevel@tonic-gate 		const void *impl_data, int caller)
17237c478bd9Sstevel@tonic-gate {
17247c478bd9Sstevel@tonic-gate 	int fatal = 0;
17257c478bd9Sstevel@tonic-gate 	int nonfatal = 0;
17267c478bd9Sstevel@tonic-gate 	int unknown = 0;
17277c478bd9Sstevel@tonic-gate 	uint32_t prierr, secerr;
17287c478bd9Sstevel@tonic-gate 	pbm_errstate_t pbm_err;
17297c478bd9Sstevel@tonic-gate 	char buf[FM_MAX_CLASS];
17307c478bd9Sstevel@tonic-gate 	pci_t *pci_p = (pci_t *)impl_data;
17317c478bd9Sstevel@tonic-gate 	pbm_t *pbm_p = pci_p->pci_pbm_p;
17327c478bd9Sstevel@tonic-gate 	int ret = 0;
17337c478bd9Sstevel@tonic-gate 	uint64_t pbm_ctl_stat;
17347c478bd9Sstevel@tonic-gate 	uint16_t pci_cfg_stat;
17357c478bd9Sstevel@tonic-gate 
17367c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pci_p->pci_common_p->pci_fm_mutex));
17377c478bd9Sstevel@tonic-gate 	pci_pbm_errstate_get(pci_p, &pbm_err);
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	derr->fme_ena = derr->fme_ena ? derr->fme_ena :
17407c478bd9Sstevel@tonic-gate 	    fm_ena_generate(0, FM_ENA_FMT1);
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 	prierr = PBM_AFSR_TO_PRIERR(pbm_err.pbm_afsr);
17437c478bd9Sstevel@tonic-gate 	secerr = PBM_AFSR_TO_SECERR(pbm_err.pbm_afsr);
17447c478bd9Sstevel@tonic-gate 
17457c478bd9Sstevel@tonic-gate 	if (derr->fme_flag == DDI_FM_ERR_EXPECTED) {
17467c478bd9Sstevel@tonic-gate 		if (caller == PCI_TRAP_CALL) {
17477c478bd9Sstevel@tonic-gate 			/*
17487c478bd9Sstevel@tonic-gate 			 * For ddi_caut_get treat all events as
17497c478bd9Sstevel@tonic-gate 			 * nonfatal. The trampoline will set
17507c478bd9Sstevel@tonic-gate 			 * err_ena = 0, err_status = NONFATAL. We only
17517c478bd9Sstevel@tonic-gate 			 * really call this function so that pci_clear_error()
17527c478bd9Sstevel@tonic-gate 			 * and ndi_fm_handler_dispatch() will get called.
17537c478bd9Sstevel@tonic-gate 			 */
17547c478bd9Sstevel@tonic-gate 			derr->fme_status = DDI_FM_NONFATAL;
17557c478bd9Sstevel@tonic-gate 			nonfatal++;
17567c478bd9Sstevel@tonic-gate 			goto done;
17577c478bd9Sstevel@tonic-gate 		} else {
17587c478bd9Sstevel@tonic-gate 			/*
17597c478bd9Sstevel@tonic-gate 			 * For ddi_caut_put treat all events as nonfatal. Here
17607c478bd9Sstevel@tonic-gate 			 * we have the handle and can call ndi_fm_acc_err_set().
17617c478bd9Sstevel@tonic-gate 			 */
17627c478bd9Sstevel@tonic-gate 			derr->fme_status = DDI_FM_NONFATAL;
17637c478bd9Sstevel@tonic-gate 			ndi_fm_acc_err_set(pbm_p->pbm_excl_handle, derr);
17647c478bd9Sstevel@tonic-gate 			nonfatal++;
17657c478bd9Sstevel@tonic-gate 			goto done;
17667c478bd9Sstevel@tonic-gate 		}
17677c478bd9Sstevel@tonic-gate 	} else if (derr->fme_flag == DDI_FM_ERR_PEEK) {
17687c478bd9Sstevel@tonic-gate 		/*
17697c478bd9Sstevel@tonic-gate 		 * For ddi_peek treat all events as nonfatal. We only
17707c478bd9Sstevel@tonic-gate 		 * really call this function so that pci_clear_error()
17717c478bd9Sstevel@tonic-gate 		 * and ndi_fm_handler_dispatch() will get called.
17727c478bd9Sstevel@tonic-gate 		 */
17737c478bd9Sstevel@tonic-gate 		nonfatal++;
17747c478bd9Sstevel@tonic-gate 		goto done;
17757c478bd9Sstevel@tonic-gate 	} else if (derr->fme_flag == DDI_FM_ERR_POKE) {
17767c478bd9Sstevel@tonic-gate 		/*
17777c478bd9Sstevel@tonic-gate 		 * For ddi_poke we can treat as nonfatal if the
17787c478bd9Sstevel@tonic-gate 		 * following conditions are met :
17797c478bd9Sstevel@tonic-gate 		 * 1. Make sure only primary error is MA/TA
17807c478bd9Sstevel@tonic-gate 		 * 2. Make sure no secondary error
17817c478bd9Sstevel@tonic-gate 		 * 3. check pci config header stat reg to see MA/TA is
17827c478bd9Sstevel@tonic-gate 		 *    logged. We cannot verify only MA/TA is recorded
17837c478bd9Sstevel@tonic-gate 		 *    since it gets much more complicated when a
17847c478bd9Sstevel@tonic-gate 		 *    PCI-to-PCI bridge is present.
17857c478bd9Sstevel@tonic-gate 		 */
17867c478bd9Sstevel@tonic-gate 		if ((prierr == PSYCHO_PCI_AFSR_E_MA) && !secerr &&
17877c478bd9Sstevel@tonic-gate 		    (pbm_err.pbm_pci.pci_cfg_stat & PCI_STAT_R_MAST_AB)) {
17887c478bd9Sstevel@tonic-gate 			nonfatal++;
17897c478bd9Sstevel@tonic-gate 			goto done;
17907c478bd9Sstevel@tonic-gate 		}
17917c478bd9Sstevel@tonic-gate 		if ((prierr == PSYCHO_PCI_AFSR_E_TA) && !secerr &&
17927c478bd9Sstevel@tonic-gate 		    (pbm_err.pbm_pci.pci_cfg_stat & PCI_STAT_R_TARG_AB)) {
17937c478bd9Sstevel@tonic-gate 			nonfatal++;
17947c478bd9Sstevel@tonic-gate 			goto done;
17957c478bd9Sstevel@tonic-gate 		}
17967c478bd9Sstevel@tonic-gate 	}
17977c478bd9Sstevel@tonic-gate 
17987c478bd9Sstevel@tonic-gate 	if (prierr || secerr) {
17997c478bd9Sstevel@tonic-gate 		ret = pbm_afsr_report(dip, derr->fme_ena, &pbm_err);
18007c478bd9Sstevel@tonic-gate 		if (ret == DDI_FM_FATAL)
18017c478bd9Sstevel@tonic-gate 			fatal++;
18027c478bd9Sstevel@tonic-gate 		else
18037c478bd9Sstevel@tonic-gate 			nonfatal++;
18047c478bd9Sstevel@tonic-gate 	}
18057c478bd9Sstevel@tonic-gate 
18067c478bd9Sstevel@tonic-gate 	ret = pci_cfg_report(dip, derr, &pbm_err.pbm_pci, caller, prierr);
18077c478bd9Sstevel@tonic-gate 	if (ret == DDI_FM_FATAL)
18087c478bd9Sstevel@tonic-gate 		fatal++;
18097c478bd9Sstevel@tonic-gate 	else if (ret == DDI_FM_NONFATAL)
18107c478bd9Sstevel@tonic-gate 		nonfatal++;
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 	pbm_ctl_stat = pbm_err.pbm_ctl_stat;
18137c478bd9Sstevel@tonic-gate 	pci_cfg_stat = pbm_err.pbm_pci.pci_cfg_stat;
18147c478bd9Sstevel@tonic-gate 
18157c478bd9Sstevel@tonic-gate 	/*
18167c478bd9Sstevel@tonic-gate 	 * PBM Received System Error - During any transaction, or
18177c478bd9Sstevel@tonic-gate 	 * at any point on the bus, some device may detect a critical
18187c478bd9Sstevel@tonic-gate 	 * error and signal a system error to the system.
18197c478bd9Sstevel@tonic-gate 	 */
18207c478bd9Sstevel@tonic-gate 	if (pbm_ctl_stat & COMMON_PCI_CTRL_SERR) {
18217c478bd9Sstevel@tonic-gate 		/*
18227c478bd9Sstevel@tonic-gate 		 * may be expected (master abort from pci-pci bridge during
18237c478bd9Sstevel@tonic-gate 		 * poke will generate SERR)
18247c478bd9Sstevel@tonic-gate 		 */
18257c478bd9Sstevel@tonic-gate 		if (derr->fme_flag != DDI_FM_ERR_POKE) {
18267c478bd9Sstevel@tonic-gate 			pbm_err.pbm_pci.pci_err_class = PCI_REC_SERR;
18277c478bd9Sstevel@tonic-gate 			(void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
18287c478bd9Sstevel@tonic-gate 			    PCI_ERROR_SUBCLASS, pbm_err.pbm_pci.pci_err_class);
18297c478bd9Sstevel@tonic-gate 			ddi_fm_ereport_post(dip, buf, derr->fme_ena,
18307c478bd9Sstevel@tonic-gate 			    DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
18317c478bd9Sstevel@tonic-gate 			    PCI_CONFIG_STATUS, DATA_TYPE_UINT16, pci_cfg_stat,
18327c478bd9Sstevel@tonic-gate 			    PCI_CONFIG_COMMAND, DATA_TYPE_UINT16,
18337c478bd9Sstevel@tonic-gate 			    pbm_err.pbm_pci.pci_cfg_comm, PCI_PA,
18347c478bd9Sstevel@tonic-gate 			    DATA_TYPE_UINT64, (uint64_t)0, NULL);
18357c478bd9Sstevel@tonic-gate 		}
183600d0963fSdilpreet 		unknown++;
18377c478bd9Sstevel@tonic-gate 	}
18387c478bd9Sstevel@tonic-gate 
18397c478bd9Sstevel@tonic-gate 	/* Streaming Byte Hole Error */
18407c478bd9Sstevel@tonic-gate 	if (pbm_ctl_stat & COMMON_PCI_CTRL_SBH_ERR) {
18417c478bd9Sstevel@tonic-gate 		if (pci_panic_on_sbh_errors)
18427c478bd9Sstevel@tonic-gate 			fatal++;
18437c478bd9Sstevel@tonic-gate 		else
18447c478bd9Sstevel@tonic-gate 			nonfatal++;
18457c478bd9Sstevel@tonic-gate 		pbm_err.pbm_err_class = PCI_PSY_SBH;
18467c478bd9Sstevel@tonic-gate 		pbm_ereport_post(dip, derr->fme_ena, &pbm_err);
18477c478bd9Sstevel@tonic-gate 	}
18487c478bd9Sstevel@tonic-gate done:
18497c478bd9Sstevel@tonic-gate 	ret = ndi_fm_handler_dispatch(dip, NULL, derr);
18507c478bd9Sstevel@tonic-gate 	if (ret == DDI_FM_FATAL) {
18517c478bd9Sstevel@tonic-gate 		fatal++;
18527c478bd9Sstevel@tonic-gate 	} else if (ret == DDI_FM_NONFATAL) {
18537c478bd9Sstevel@tonic-gate 		nonfatal++;
18547c478bd9Sstevel@tonic-gate 	} else if (ret == DDI_FM_UNKNOWN) {
18557c478bd9Sstevel@tonic-gate 		unknown++;
18567c478bd9Sstevel@tonic-gate 	}
18577c478bd9Sstevel@tonic-gate 
18587c478bd9Sstevel@tonic-gate 	/*
18597c478bd9Sstevel@tonic-gate 	 * rserr not claimed as nonfatal by a child is treated as fatal
18607c478bd9Sstevel@tonic-gate 	 */
186100d0963fSdilpreet 	if (unknown && !nonfatal && !fatal)
18627c478bd9Sstevel@tonic-gate 		fatal++;
18637c478bd9Sstevel@tonic-gate 
18647c478bd9Sstevel@tonic-gate 	/* Cleanup and reset error bits */
18657c478bd9Sstevel@tonic-gate 	pci_clear_error(pci_p, &pbm_err);
18667c478bd9Sstevel@tonic-gate 
18677c478bd9Sstevel@tonic-gate 	return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
18687c478bd9Sstevel@tonic-gate 	    (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
18697c478bd9Sstevel@tonic-gate }
18707c478bd9Sstevel@tonic-gate 
18717c478bd9Sstevel@tonic-gate int
pci_check_error(pci_t * pci_p)18727c478bd9Sstevel@tonic-gate pci_check_error(pci_t *pci_p)
18737c478bd9Sstevel@tonic-gate {
18747c478bd9Sstevel@tonic-gate 	pbm_t *pbm_p = pci_p->pci_pbm_p;
18757c478bd9Sstevel@tonic-gate 	uint16_t pci_cfg_stat;
18767c478bd9Sstevel@tonic-gate 	uint64_t pbm_ctl_stat, pbm_afsr;
18777c478bd9Sstevel@tonic-gate 
18787c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pci_p->pci_common_p->pci_fm_mutex));
18797c478bd9Sstevel@tonic-gate 
18807c478bd9Sstevel@tonic-gate 	pci_cfg_stat = pbm_p->pbm_config_header->ch_status_reg;
18817c478bd9Sstevel@tonic-gate 	pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
18827c478bd9Sstevel@tonic-gate 	pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
18837c478bd9Sstevel@tonic-gate 
18847c478bd9Sstevel@tonic-gate 	if ((pci_cfg_stat & (PCI_STAT_S_PERROR | PCI_STAT_S_TARG_AB |
18857c478bd9Sstevel@tonic-gate 				PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB |
18867c478bd9Sstevel@tonic-gate 				PCI_STAT_S_SYSERR | PCI_STAT_PERROR)) ||
18877c478bd9Sstevel@tonic-gate 			(pbm_ctl_stat & (COMMON_PCI_CTRL_SBH_ERR |
18887c478bd9Sstevel@tonic-gate 				COMMON_PCI_CTRL_SERR)) ||
18897c478bd9Sstevel@tonic-gate 			(PBM_AFSR_TO_PRIERR(pbm_afsr)))
18907c478bd9Sstevel@tonic-gate 		return (1);
18917c478bd9Sstevel@tonic-gate 
18927c478bd9Sstevel@tonic-gate 	return (0);
18937c478bd9Sstevel@tonic-gate 
18947c478bd9Sstevel@tonic-gate }
18957c478bd9Sstevel@tonic-gate 
18967c478bd9Sstevel@tonic-gate /*
18977c478bd9Sstevel@tonic-gate  * Function used to gather PBM/PCI error state for the
18987c478bd9Sstevel@tonic-gate  * pci_pbm_err_handler. This function must be called while pci_fm_mutex
18997c478bd9Sstevel@tonic-gate  * is held.
19007c478bd9Sstevel@tonic-gate  */
19017c478bd9Sstevel@tonic-gate static void
pci_pbm_errstate_get(pci_t * pci_p,pbm_errstate_t * pbm_err_p)19027c478bd9Sstevel@tonic-gate pci_pbm_errstate_get(pci_t *pci_p, pbm_errstate_t *pbm_err_p)
19037c478bd9Sstevel@tonic-gate {
19047c478bd9Sstevel@tonic-gate 	pbm_t *pbm_p = pci_p->pci_pbm_p;
19057c478bd9Sstevel@tonic-gate 
19067c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&pci_p->pci_common_p->pci_fm_mutex));
19077c478bd9Sstevel@tonic-gate 	bzero(pbm_err_p, sizeof (pbm_errstate_t));
19087c478bd9Sstevel@tonic-gate 
19097c478bd9Sstevel@tonic-gate 	/*
19107c478bd9Sstevel@tonic-gate 	 * Capture all pbm error state for later logging
19117c478bd9Sstevel@tonic-gate 	 */
19127c478bd9Sstevel@tonic-gate 	pbm_err_p->pbm_bridge_type = PCI_BRIDGE_TYPE(pci_p->pci_common_p);
19137c478bd9Sstevel@tonic-gate 	pbm_err_p->pbm_pci.pci_cfg_stat =
19147c478bd9Sstevel@tonic-gate 		pbm_p->pbm_config_header->ch_status_reg;
19157c478bd9Sstevel@tonic-gate 	pbm_err_p->pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
19167c478bd9Sstevel@tonic-gate 	pbm_err_p->pbm_pci.pci_cfg_comm =
19177c478bd9Sstevel@tonic-gate 		pbm_p->pbm_config_header->ch_command_reg;
19187c478bd9Sstevel@tonic-gate 	pbm_err_p->pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
19197c478bd9Sstevel@tonic-gate 	pbm_err_p->pbm_afar = *pbm_p->pbm_async_flt_addr_reg;
19207c478bd9Sstevel@tonic-gate 	pbm_err_p->pbm_pci.pci_pa = *pbm_p->pbm_async_flt_addr_reg;
19217c478bd9Sstevel@tonic-gate }
19227c478bd9Sstevel@tonic-gate 
19237c478bd9Sstevel@tonic-gate void
pbm_clear_error(pbm_t * pbm_p)19247c478bd9Sstevel@tonic-gate pbm_clear_error(pbm_t *pbm_p)
19257c478bd9Sstevel@tonic-gate {
19267c478bd9Sstevel@tonic-gate 	uint64_t pbm_afsr, pbm_ctl_stat;
19277c478bd9Sstevel@tonic-gate 
19287c478bd9Sstevel@tonic-gate 	/*
19297c478bd9Sstevel@tonic-gate 	 * for poke() support - called from POKE_FLUSH. Spin waiting
19307c478bd9Sstevel@tonic-gate 	 * for MA, TA or SERR to be cleared by a pbm_error_intr().
19317c478bd9Sstevel@tonic-gate 	 * We have to wait for SERR too in case the device is beyond
19327c478bd9Sstevel@tonic-gate 	 * a pci-pci bridge.
19337c478bd9Sstevel@tonic-gate 	 */
19347c478bd9Sstevel@tonic-gate 	pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
19357c478bd9Sstevel@tonic-gate 	pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
19367c478bd9Sstevel@tonic-gate 	while (((pbm_afsr >> PSYCHO_PCI_AFSR_PE_SHIFT) &
19377c478bd9Sstevel@tonic-gate 	    (PSYCHO_PCI_AFSR_E_MA | PSYCHO_PCI_AFSR_E_TA)) ||
19387c478bd9Sstevel@tonic-gate 	    (pbm_ctl_stat & COMMON_PCI_CTRL_SERR)) {
19397c478bd9Sstevel@tonic-gate 		pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
19407c478bd9Sstevel@tonic-gate 		pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
19417c478bd9Sstevel@tonic-gate 	}
19427c478bd9Sstevel@tonic-gate }
19437c478bd9Sstevel@tonic-gate 
19447c478bd9Sstevel@tonic-gate /*ARGSUSED*/
19457c478bd9Sstevel@tonic-gate void
pci_format_addr(dev_info_t * dip,uint64_t * afar,uint64_t afsr)19467c478bd9Sstevel@tonic-gate pci_format_addr(dev_info_t *dip, uint64_t *afar, uint64_t afsr)
19477c478bd9Sstevel@tonic-gate {
19487c478bd9Sstevel@tonic-gate 	/*
19497c478bd9Sstevel@tonic-gate 	 * For Psycho the full address is stored in hardware. So
19507c478bd9Sstevel@tonic-gate 	 * there is no need to format it.
19517c478bd9Sstevel@tonic-gate 	 */
19527c478bd9Sstevel@tonic-gate }
19537c478bd9Sstevel@tonic-gate 
19547c478bd9Sstevel@tonic-gate /*ARGSUSED*/
19557c478bd9Sstevel@tonic-gate int
pci_bus_quiesce(pci_t * pci_p,dev_info_t * dip,void * result)19567c478bd9Sstevel@tonic-gate pci_bus_quiesce(pci_t *pci_p, dev_info_t *dip, void *result)
19577c478bd9Sstevel@tonic-gate {
19587c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
19597c478bd9Sstevel@tonic-gate }
19607c478bd9Sstevel@tonic-gate 
19617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
19627c478bd9Sstevel@tonic-gate int
pci_bus_unquiesce(pci_t * pci_p,dev_info_t * dip,void * result)19637c478bd9Sstevel@tonic-gate pci_bus_unquiesce(pci_t *pci_p, dev_info_t *dip, void *result)
19647c478bd9Sstevel@tonic-gate {
19657c478bd9Sstevel@tonic-gate 	return (DDI_FAILURE);
19667c478bd9Sstevel@tonic-gate }
19677c478bd9Sstevel@tonic-gate 
1968d0662dbfSelowe int
pci_reloc_getkey(void)1969d0662dbfSelowe pci_reloc_getkey(void)
1970d0662dbfSelowe {
1971d0662dbfSelowe 	return (0x100);
1972d0662dbfSelowe }
1973d0662dbfSelowe 
19747c478bd9Sstevel@tonic-gate void
pci_vmem_free(iommu_t * iommu_p,ddi_dma_impl_t * mp,void * dvma_addr,size_t npages)19757c478bd9Sstevel@tonic-gate pci_vmem_free(iommu_t *iommu_p, ddi_dma_impl_t *mp, void *dvma_addr,
19767c478bd9Sstevel@tonic-gate     size_t npages)
19777c478bd9Sstevel@tonic-gate {
19787c478bd9Sstevel@tonic-gate 	pci_vmem_do_free(iommu_p, dvma_addr, npages,
19797c478bd9Sstevel@tonic-gate 	    (mp->dmai_flags & DMAI_FLAGS_VMEMCACHE));
19807c478bd9Sstevel@tonic-gate }
19817c478bd9Sstevel@tonic-gate 
19827c478bd9Sstevel@tonic-gate 
19837c478bd9Sstevel@tonic-gate /*
19847c478bd9Sstevel@tonic-gate  * NOTE: This call is only used by legacy systems (eg. E250 and E450) that
19857c478bd9Sstevel@tonic-gate  * require unregistering the pci driver's thermal intrerrupt handler before
19867c478bd9Sstevel@tonic-gate  * they can register their own.
19877c478bd9Sstevel@tonic-gate  */
19887c478bd9Sstevel@tonic-gate void
pci_thermal_rem_intr(dev_info_t * rdip,uint_t inum)19897c478bd9Sstevel@tonic-gate pci_thermal_rem_intr(dev_info_t *rdip, uint_t inum)
19907c478bd9Sstevel@tonic-gate {
19917c478bd9Sstevel@tonic-gate 	pci_t		*pci_p;
19927c478bd9Sstevel@tonic-gate 	dev_info_t	*pdip;
19937c478bd9Sstevel@tonic-gate 	uint32_t	dev_mondo, pci_mondo;
19947c478bd9Sstevel@tonic-gate 	int 		instance;
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate 	for (pdip = ddi_get_parent(rdip); pdip; pdip = ddi_get_parent(pdip)) {
19977c478bd9Sstevel@tonic-gate 		if (strcmp(ddi_driver_name(pdip), "pcipsy") == 0)
19987c478bd9Sstevel@tonic-gate 			break;
19997c478bd9Sstevel@tonic-gate 	}
20007c478bd9Sstevel@tonic-gate 
20017c478bd9Sstevel@tonic-gate 	if (!pdip) {
20027c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "pci_thermal_rem_intr() no pcipsy parent\n");
20037c478bd9Sstevel@tonic-gate 		return;
20047c478bd9Sstevel@tonic-gate 	}
20057c478bd9Sstevel@tonic-gate 
20067c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(pdip);
20077c478bd9Sstevel@tonic-gate 	pci_p = get_pci_soft_state(instance);
20087c478bd9Sstevel@tonic-gate 
20097c478bd9Sstevel@tonic-gate 	/* Calculate the requesting device's mondo */
20107c478bd9Sstevel@tonic-gate 	dev_mondo = pci_xlate_intr(pci_p->pci_dip, rdip, pci_p->pci_ib_p,
2011a195726fSgovinda 	    IB_MONDO_TO_INO(i_ddi_get_inum(rdip, inum)));
20127c478bd9Sstevel@tonic-gate 
20137c478bd9Sstevel@tonic-gate 	/* get pci's thermal mondo */
20147c478bd9Sstevel@tonic-gate 	pci_mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
20157c478bd9Sstevel@tonic-gate 	    pci_p->pci_inos[CBNINTR_THERMAL]);
20167c478bd9Sstevel@tonic-gate 	pci_mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, pci_mondo);
20177c478bd9Sstevel@tonic-gate 
20187c478bd9Sstevel@tonic-gate 	if (pci_mondo == dev_mondo) {
20197c478bd9Sstevel@tonic-gate 		DEBUG2(DBG_ATTACH, rdip, "pci_thermal_rem_intr unregistered "
20207c478bd9Sstevel@tonic-gate 		    "for dip=%s%d:", ddi_driver_name(rdip),
20217c478bd9Sstevel@tonic-gate 		    ddi_get_instance(rdip));
2022b0fc0e77Sgovinda 		VERIFY(rem_ivintr(pci_mondo, pci_pil[CBNINTR_THERMAL]) == 0);
20237c478bd9Sstevel@tonic-gate 	}
20247c478bd9Sstevel@tonic-gate }
202549f91442Ssuha 
202649f91442Ssuha /*
202749f91442Ssuha  * pci_iommu_bypass_end_configure
202849f91442Ssuha  *
202949f91442Ssuha  * Support for 40-bit bus width to UPA in DVMA and iommu bypass transfers:
203049f91442Ssuha  */
203149f91442Ssuha 
203249f91442Ssuha dma_bypass_addr_t
pci_iommu_bypass_end_configure(void)203349f91442Ssuha pci_iommu_bypass_end_configure(void)
203449f91442Ssuha {
203549f91442Ssuha 
203649f91442Ssuha 	return ((dma_bypass_addr_t)UPA_IOMMU_BYPASS_END);
203749f91442Ssuha }
2038