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