10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51817Sarutz * Common Development and Distribution License (the "License").
61817Sarutz * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*4039Skd93003 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * Psycho+ specifics implementation:
300Sstevel@tonic-gate * interrupt mapping register
310Sstevel@tonic-gate * PBM configuration
320Sstevel@tonic-gate * ECC and PBM error handling
330Sstevel@tonic-gate * Iommu mapping handling
340Sstevel@tonic-gate * Streaming Cache flushing
350Sstevel@tonic-gate */
360Sstevel@tonic-gate
370Sstevel@tonic-gate #include <sys/types.h>
380Sstevel@tonic-gate #include <sys/kmem.h>
390Sstevel@tonic-gate #include <sys/sysmacros.h>
400Sstevel@tonic-gate #include <sys/async.h>
410Sstevel@tonic-gate #include <sys/systm.h>
420Sstevel@tonic-gate #include <sys/intreg.h> /* UPAID_TO_IGN() */
432973Sgovinda #include <sys/ivintr.h>
440Sstevel@tonic-gate #include <sys/sunddi.h>
450Sstevel@tonic-gate #include <sys/sunndi.h>
460Sstevel@tonic-gate #include <sys/machsystm.h>
470Sstevel@tonic-gate #include <sys/fm/util.h>
480Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
490Sstevel@tonic-gate #include <sys/iommutsb.h>
500Sstevel@tonic-gate #include <sys/spl.h>
510Sstevel@tonic-gate #include <sys/fm/util.h>
520Sstevel@tonic-gate #include <sys/fm/protocol.h>
530Sstevel@tonic-gate #include <sys/fm/io/pci.h>
540Sstevel@tonic-gate #include <sys/fm/io/sun4upci.h>
550Sstevel@tonic-gate #include <sys/pci/pci_obj.h>
560Sstevel@tonic-gate #include <sys/pci/pcipsy.h>
570Sstevel@tonic-gate
580Sstevel@tonic-gate #ifdef _STARFIRE
590Sstevel@tonic-gate #include <sys/starfire.h>
600Sstevel@tonic-gate #endif /* _STARFIRE */
610Sstevel@tonic-gate
620Sstevel@tonic-gate static uint32_t pci_identity_init(pci_t *pci_p);
630Sstevel@tonic-gate static int pci_intr_setup(pci_t *pci_p);
640Sstevel@tonic-gate static void pci_pbm_errstate_get(pci_t *pci_p, pbm_errstate_t *pbm_err_p);
650Sstevel@tonic-gate
660Sstevel@tonic-gate static pci_ksinfo_t *pci_name_kstat;
670Sstevel@tonic-gate
680Sstevel@tonic-gate /*LINTLIBRARY*/
690Sstevel@tonic-gate /* called by pci_attach() DDI_ATTACH to initialize pci objects */
700Sstevel@tonic-gate int
pci_obj_setup(pci_t * pci_p)710Sstevel@tonic-gate pci_obj_setup(pci_t *pci_p)
720Sstevel@tonic-gate {
730Sstevel@tonic-gate pci_common_t *cmn_p;
740Sstevel@tonic-gate int ret;
750Sstevel@tonic-gate
760Sstevel@tonic-gate mutex_enter(&pci_global_mutex);
770Sstevel@tonic-gate cmn_p = get_pci_common_soft_state(pci_p->pci_id);
780Sstevel@tonic-gate if (cmn_p == NULL) {
790Sstevel@tonic-gate uint_t id = pci_p->pci_id;
800Sstevel@tonic-gate if (alloc_pci_common_soft_state(id) != DDI_SUCCESS) {
810Sstevel@tonic-gate mutex_exit(&pci_global_mutex);
820Sstevel@tonic-gate return (DDI_FAILURE);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate cmn_p = get_pci_common_soft_state(id);
850Sstevel@tonic-gate cmn_p->pci_common_id = id;
860Sstevel@tonic-gate }
870Sstevel@tonic-gate
880Sstevel@tonic-gate ASSERT((pci_p->pci_side == 0) || (pci_p->pci_side == 1));
890Sstevel@tonic-gate if (cmn_p->pci_p[pci_p->pci_side]) {
900Sstevel@tonic-gate /* second side attach */
910Sstevel@tonic-gate pci_p->pci_side = PCI_OTHER_SIDE(pci_p->pci_side);
920Sstevel@tonic-gate ASSERT(cmn_p->pci_p[pci_p->pci_side] == NULL);
930Sstevel@tonic-gate }
940Sstevel@tonic-gate
950Sstevel@tonic-gate cmn_p->pci_p[pci_p->pci_side] = pci_p;
960Sstevel@tonic-gate pci_p->pci_common_p = cmn_p;
970Sstevel@tonic-gate
980Sstevel@tonic-gate if (cmn_p->pci_common_refcnt == 0) {
990Sstevel@tonic-gate /* Perform allocation first to avoid delicate unwinding. */
1000Sstevel@tonic-gate if (pci_alloc_tsb(pci_p) != DDI_SUCCESS) {
1010Sstevel@tonic-gate cmn_p->pci_p[pci_p->pci_side] = NULL;
1020Sstevel@tonic-gate pci_p->pci_common_p = NULL;
1030Sstevel@tonic-gate free_pci_common_soft_state(cmn_p->pci_common_id);
1040Sstevel@tonic-gate mutex_exit(&pci_global_mutex);
1050Sstevel@tonic-gate return (DDI_FAILURE);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate cmn_p->pci_common_tsb_cookie = pci_p->pci_tsb_cookie;
1080Sstevel@tonic-gate cmn_p->pci_chip_id = pci_identity_init(pci_p);
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate ib_create(pci_p);
1110Sstevel@tonic-gate cmn_p->pci_common_ib_p = pci_p->pci_ib_p;
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate cb_create(pci_p);
1140Sstevel@tonic-gate cmn_p->pci_common_cb_p = pci_p->pci_cb_p;
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate iommu_create(pci_p);
1170Sstevel@tonic-gate cmn_p->pci_common_iommu_p = pci_p->pci_iommu_p;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate ecc_create(pci_p);
1200Sstevel@tonic-gate cmn_p->pci_common_ecc_p = pci_p->pci_ecc_p;
1210Sstevel@tonic-gate } else {
1220Sstevel@tonic-gate ASSERT(cmn_p->pci_common_refcnt == 1);
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate pci_p->pci_tsb_cookie = cmn_p->pci_common_tsb_cookie;
1250Sstevel@tonic-gate pci_p->pci_ib_p = cmn_p->pci_common_ib_p;
1260Sstevel@tonic-gate pci_p->pci_cb_p = cmn_p->pci_common_cb_p;
1270Sstevel@tonic-gate pci_p->pci_iommu_p = cmn_p->pci_common_iommu_p;
1280Sstevel@tonic-gate pci_p->pci_ecc_p = cmn_p->pci_common_ecc_p;
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate pbm_create(pci_p);
1320Sstevel@tonic-gate sc_create(pci_p);
1330Sstevel@tonic-gate
1340Sstevel@tonic-gate pci_fm_create(pci_p);
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate if ((ret = pci_intr_setup(pci_p)) != DDI_SUCCESS)
1370Sstevel@tonic-gate goto done;
1380Sstevel@tonic-gate if (CHIP_TYPE(pci_p) == PCI_CHIP_PSYCHO)
1390Sstevel@tonic-gate pci_kstat_create(pci_p);
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate cmn_p->pci_common_attachcnt++;
1420Sstevel@tonic-gate cmn_p->pci_common_refcnt++;
1430Sstevel@tonic-gate done:
1440Sstevel@tonic-gate mutex_exit(&pci_global_mutex);
1450Sstevel@tonic-gate if (ret != DDI_SUCCESS)
1460Sstevel@tonic-gate cmn_err(CE_NOTE, "Interrupt register failure, returning 0x%x\n",
1470Sstevel@tonic-gate ret);
1480Sstevel@tonic-gate return (ret);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate /* called by pci_detach() DDI_DETACH to destroy pci objects */
1520Sstevel@tonic-gate void
pci_obj_destroy(pci_t * pci_p)1530Sstevel@tonic-gate pci_obj_destroy(pci_t *pci_p)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate pci_common_t *cmn_p;
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate mutex_enter(&pci_global_mutex);
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate cmn_p = pci_p->pci_common_p;
1600Sstevel@tonic-gate cmn_p->pci_common_refcnt--;
1610Sstevel@tonic-gate cmn_p->pci_common_attachcnt--;
1620Sstevel@tonic-gate
1630Sstevel@tonic-gate pci_kstat_destroy(pci_p);
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate sc_destroy(pci_p);
1660Sstevel@tonic-gate pbm_destroy(pci_p);
1670Sstevel@tonic-gate pci_fm_destroy(pci_p);
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate if (cmn_p->pci_common_refcnt != 0) {
1700Sstevel@tonic-gate cmn_p->pci_p[pci_p->pci_side] = NULL;
1710Sstevel@tonic-gate mutex_exit(&pci_global_mutex);
1720Sstevel@tonic-gate return;
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate ecc_destroy(pci_p);
1760Sstevel@tonic-gate iommu_destroy(pci_p);
1770Sstevel@tonic-gate cb_destroy(pci_p);
1780Sstevel@tonic-gate ib_destroy(pci_p);
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate free_pci_common_soft_state(cmn_p->pci_common_id);
1810Sstevel@tonic-gate pci_intr_teardown(pci_p);
1820Sstevel@tonic-gate mutex_exit(&pci_global_mutex);
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate /* called by pci_attach() DDI_RESUME to (re)initialize pci objects */
1860Sstevel@tonic-gate void
pci_obj_resume(pci_t * pci_p)1870Sstevel@tonic-gate pci_obj_resume(pci_t *pci_p)
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate pci_common_t *cmn_p = pci_p->pci_common_p;
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate mutex_enter(&pci_global_mutex);
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate if (cmn_p->pci_common_attachcnt == 0) {
1940Sstevel@tonic-gate ib_configure(pci_p->pci_ib_p);
1950Sstevel@tonic-gate iommu_configure(pci_p->pci_iommu_p);
1960Sstevel@tonic-gate ecc_configure(pci_p);
1970Sstevel@tonic-gate ib_resume(pci_p->pci_ib_p);
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate pbm_configure(pci_p->pci_pbm_p);
2010Sstevel@tonic-gate sc_configure(pci_p->pci_sc_p);
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate if (cmn_p->pci_common_attachcnt == 0)
2040Sstevel@tonic-gate cb_resume(pci_p->pci_cb_p);
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate pbm_resume(pci_p->pci_pbm_p);
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate cmn_p->pci_common_attachcnt++;
2090Sstevel@tonic-gate mutex_exit(&pci_global_mutex);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate /* called by pci_detach() DDI_SUSPEND to suspend pci objects */
2130Sstevel@tonic-gate void
pci_obj_suspend(pci_t * pci_p)2140Sstevel@tonic-gate pci_obj_suspend(pci_t *pci_p)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate mutex_enter(&pci_global_mutex);
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate pbm_suspend(pci_p->pci_pbm_p);
2190Sstevel@tonic-gate if (!--pci_p->pci_common_p->pci_common_attachcnt) {
2200Sstevel@tonic-gate ib_suspend(pci_p->pci_ib_p);
2210Sstevel@tonic-gate cb_suspend(pci_p->pci_cb_p);
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate mutex_exit(&pci_global_mutex);
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate static uint32_t javelin_prom_fix[] = {0xfff800, 0, 0, 0x3f};
2280Sstevel@tonic-gate static int
pci_intr_setup(pci_t * pci_p)2290Sstevel@tonic-gate pci_intr_setup(pci_t *pci_p)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate extern char *platform;
2320Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip;
2330Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p;
2340Sstevel@tonic-gate cb_t *cb_p = pci_p->pci_cb_p;
2350Sstevel@tonic-gate int i, no_of_intrs;
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate * This is a hack to fix a broken imap entry in the javelin PROM.
2390Sstevel@tonic-gate * see bugid 4226603
2400Sstevel@tonic-gate */
2410Sstevel@tonic-gate if (strcmp((const char *)&platform, "SUNW,Ultra-250") == 0)
2420Sstevel@tonic-gate (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
2430Sstevel@tonic-gate "interrupt-map-mask", (caddr_t)javelin_prom_fix,
2440Sstevel@tonic-gate sizeof (javelin_prom_fix));
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * Get the interrupts property.
2480Sstevel@tonic-gate */
249506Scth if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2500Sstevel@tonic-gate "interrupts", (caddr_t)&pci_p->pci_inos,
2510Sstevel@tonic-gate &pci_p->pci_inos_len) != DDI_SUCCESS)
2520Sstevel@tonic-gate cmn_err(CE_PANIC, "%s%d: no interrupts property\n",
2530Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate /*
2560Sstevel@tonic-gate * figure out number of interrupts in the "interrupts" property
2570Sstevel@tonic-gate * and convert them all into ino.
2580Sstevel@tonic-gate */
2590Sstevel@tonic-gate i = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "#interrupt-cells", 1);
2600Sstevel@tonic-gate i = CELLS_1275_TO_BYTES(i);
2610Sstevel@tonic-gate no_of_intrs = pci_p->pci_inos_len / i;
2620Sstevel@tonic-gate for (i = 0; i < no_of_intrs; i++)
2630Sstevel@tonic-gate pci_p->pci_inos[i] = IB_MONDO_TO_INO(pci_p->pci_inos[i]);
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate if (pci_p->pci_common_p->pci_common_refcnt == 0) {
2660Sstevel@tonic-gate cb_p->cb_no_of_inos = no_of_intrs;
2670Sstevel@tonic-gate if (i = cb_register_intr(pci_p))
2680Sstevel@tonic-gate goto teardown;
2690Sstevel@tonic-gate if (i = ecc_register_intr(pci_p))
2700Sstevel@tonic-gate goto teardown;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate intr_dist_add(cb_intr_dist, cb_p);
2730Sstevel@tonic-gate cb_enable_intr(pci_p);
2740Sstevel@tonic-gate ecc_enable_intr(pci_p);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate if (i = pbm_register_intr(pbm_p)) {
2780Sstevel@tonic-gate if (pci_p->pci_common_p->pci_common_refcnt == 0)
2790Sstevel@tonic-gate intr_dist_rem(cb_intr_dist, cb_p);
2800Sstevel@tonic-gate goto teardown;
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate intr_dist_add(pbm_intr_dist, pbm_p);
2830Sstevel@tonic-gate ib_intr_enable(pci_p, pci_p->pci_inos[CBNINTR_PBM]);
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate if (pci_p->pci_common_p->pci_common_refcnt == 0)
2860Sstevel@tonic-gate intr_dist_add_weighted(ib_intr_dist_all, pci_p->pci_ib_p);
2870Sstevel@tonic-gate return (DDI_SUCCESS);
2880Sstevel@tonic-gate teardown:
2890Sstevel@tonic-gate pci_intr_teardown(pci_p);
2900Sstevel@tonic-gate return (i);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate /*
2940Sstevel@tonic-gate * pci_fix_ranges - fixes the config space entry of the "ranges"
2950Sstevel@tonic-gate * property on psycho+ platforms
2960Sstevel@tonic-gate */
2970Sstevel@tonic-gate void
pci_fix_ranges(pci_ranges_t * rng_p,int rng_entries)2980Sstevel@tonic-gate pci_fix_ranges(pci_ranges_t *rng_p, int rng_entries)
2990Sstevel@tonic-gate {
3000Sstevel@tonic-gate int i;
3010Sstevel@tonic-gate for (i = 0; i < rng_entries; i++, rng_p++)
3020Sstevel@tonic-gate if ((rng_p->child_high & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG)
3030Sstevel@tonic-gate rng_p->parent_low |= rng_p->child_high;
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate /*
3070Sstevel@tonic-gate * map_pci_registers
3080Sstevel@tonic-gate *
3090Sstevel@tonic-gate * This function is called from the attach routine to map the registers
3100Sstevel@tonic-gate * accessed by this driver.
3110Sstevel@tonic-gate *
3120Sstevel@tonic-gate * used by: pci_attach()
3130Sstevel@tonic-gate *
3140Sstevel@tonic-gate * return value: DDI_FAILURE on failure
3150Sstevel@tonic-gate */
3160Sstevel@tonic-gate int
map_pci_registers(pci_t * pci_p,dev_info_t * dip)3170Sstevel@tonic-gate map_pci_registers(pci_t *pci_p, dev_info_t *dip)
3180Sstevel@tonic-gate {
3190Sstevel@tonic-gate ddi_device_acc_attr_t attr;
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3220Sstevel@tonic-gate attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
3250Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 0, &pci_p->pci_address[0], 0, 0,
3260Sstevel@tonic-gate &attr, &pci_p->pci_ac[0]) != DDI_SUCCESS) {
3270Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unable to map reg entry 0\n",
3280Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
3290Sstevel@tonic-gate return (DDI_FAILURE);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate /*
3320Sstevel@tonic-gate * if we don't have streaming buffer, then we don't have
3330Sstevel@tonic-gate * pci_address[2].
3340Sstevel@tonic-gate */
3350Sstevel@tonic-gate if (pci_stream_buf_exists &&
3360Sstevel@tonic-gate ddi_regs_map_setup(dip, 2, &pci_p->pci_address[2], 0, 0,
3370Sstevel@tonic-gate &attr, &pci_p->pci_ac[2]) != DDI_SUCCESS) {
3380Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unable to map reg entry 2\n",
3390Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
3400Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[0]);
3410Sstevel@tonic-gate return (DDI_FAILURE);
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * The second register set contains the bridge's configuration
3460Sstevel@tonic-gate * header. This header is at the very beginning of the bridge's
3470Sstevel@tonic-gate * configuration space. This space has litte-endian byte order.
3480Sstevel@tonic-gate */
3490Sstevel@tonic-gate attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
3500Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 1, &pci_p->pci_address[1], 0,
3510Sstevel@tonic-gate PCI_CONF_HDR_SIZE, &attr, &pci_p->pci_ac[1]) != DDI_SUCCESS) {
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unable to map reg entry 1\n",
3540Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
3550Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[0]);
3560Sstevel@tonic-gate if (pci_stream_buf_exists)
3570Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[2]);
3580Sstevel@tonic-gate return (DDI_FAILURE);
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate DEBUG3(DBG_ATTACH, dip, "address (%p,%p,%p)\n",
3610Sstevel@tonic-gate pci_p->pci_address[0], pci_p->pci_address[1],
3620Sstevel@tonic-gate pci_p->pci_address[2]);
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate return (DDI_SUCCESS);
3650Sstevel@tonic-gate }
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate /*
3680Sstevel@tonic-gate * unmap_pci_registers:
3690Sstevel@tonic-gate *
3700Sstevel@tonic-gate * This routine unmap the registers mapped by map_pci_registers.
3710Sstevel@tonic-gate *
3720Sstevel@tonic-gate * used by: pci_detach()
3730Sstevel@tonic-gate *
3740Sstevel@tonic-gate * return value: none
3750Sstevel@tonic-gate */
3760Sstevel@tonic-gate void
unmap_pci_registers(pci_t * pci_p)3770Sstevel@tonic-gate unmap_pci_registers(pci_t *pci_p)
3780Sstevel@tonic-gate {
3790Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[0]);
3800Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[1]);
3810Sstevel@tonic-gate if (pci_stream_buf_exists)
3820Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[2]);
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate /*
3860Sstevel@tonic-gate * These convenience wrappers relies on map_pci_registers() to setup
3870Sstevel@tonic-gate * pci_address[0-2] correctly at first.
3880Sstevel@tonic-gate */
3890Sstevel@tonic-gate /* The psycho+ reg base is at 1fe.0000.0000 */
3900Sstevel@tonic-gate static uintptr_t
get_reg_base(pci_t * pci_p)3910Sstevel@tonic-gate get_reg_base(pci_t *pci_p)
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate return ((uintptr_t)pci_p->pci_address[pci_stream_buf_exists ? 2 : 0]);
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate /* The psycho+ config reg base is always the 2nd reg entry */
3970Sstevel@tonic-gate static uintptr_t
get_config_reg_base(pci_t * pci_p)3980Sstevel@tonic-gate get_config_reg_base(pci_t *pci_p)
3990Sstevel@tonic-gate {
4000Sstevel@tonic-gate return ((uintptr_t)(pci_p->pci_address[1]));
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate uint64_t
ib_get_map_reg(ib_mondo_t mondo,uint32_t cpu_id)4040Sstevel@tonic-gate ib_get_map_reg(ib_mondo_t mondo, uint32_t cpu_id)
4050Sstevel@tonic-gate {
4060Sstevel@tonic-gate return ((mondo) | (cpu_id << COMMON_INTR_MAP_REG_TID_SHIFT) |
4070Sstevel@tonic-gate COMMON_INTR_MAP_REG_VALID);
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate uint32_t
ib_map_reg_get_cpu(volatile uint64_t reg)4120Sstevel@tonic-gate ib_map_reg_get_cpu(volatile uint64_t reg)
4130Sstevel@tonic-gate {
4140Sstevel@tonic-gate return ((reg & COMMON_INTR_MAP_REG_TID) >>
4150Sstevel@tonic-gate COMMON_INTR_MAP_REG_TID_SHIFT);
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate
4180Sstevel@tonic-gate uint64_t *
ib_intr_map_reg_addr(ib_t * ib_p,ib_ino_t ino)4190Sstevel@tonic-gate ib_intr_map_reg_addr(ib_t *ib_p, ib_ino_t ino)
4200Sstevel@tonic-gate {
4210Sstevel@tonic-gate uint64_t *addr;
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate if (ino & 0x20)
4240Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_obio_intr_map_regs +
4250Sstevel@tonic-gate (((uint_t)ino & 0x1f) << 3));
4260Sstevel@tonic-gate else
4270Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_slot_intr_map_regs +
4280Sstevel@tonic-gate (((uint_t)ino & 0x3c) << 1));
4290Sstevel@tonic-gate return (addr);
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate uint64_t *
ib_clear_intr_reg_addr(ib_t * ib_p,ib_ino_t ino)4330Sstevel@tonic-gate ib_clear_intr_reg_addr(ib_t *ib_p, ib_ino_t ino)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate uint64_t *addr;
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate if (ino & 0x20)
4380Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_obio_clear_intr_regs +
4390Sstevel@tonic-gate (((uint_t)ino & 0x1f) << 3));
4400Sstevel@tonic-gate else
4410Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_slot_clear_intr_regs +
4420Sstevel@tonic-gate (((uint_t)ino & 0x1f) << 3));
4430Sstevel@tonic-gate return (addr);
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate * psycho have one mapping register per slot
4480Sstevel@tonic-gate */
4490Sstevel@tonic-gate void
ib_ino_map_reg_share(ib_t * ib_p,ib_ino_t ino,ib_ino_info_t * ino_p)4500Sstevel@tonic-gate ib_ino_map_reg_share(ib_t *ib_p, ib_ino_t ino, ib_ino_info_t *ino_p)
4510Sstevel@tonic-gate {
4520Sstevel@tonic-gate if (!IB_IS_OBIO_INO(ino)) {
4530Sstevel@tonic-gate ASSERT(ino_p->ino_slot_no < 8);
4540Sstevel@tonic-gate ib_p->ib_map_reg_counters[ino_p->ino_slot_no]++;
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate /*
4590Sstevel@tonic-gate * return true if the ino shares mapping register with other interrupts
4600Sstevel@tonic-gate * of the same slot, or is still shared by other On-board devices.
4610Sstevel@tonic-gate */
4620Sstevel@tonic-gate int
ib_ino_map_reg_unshare(ib_t * ib_p,ib_ino_t ino,ib_ino_info_t * ino_p)4630Sstevel@tonic-gate ib_ino_map_reg_unshare(ib_t *ib_p, ib_ino_t ino, ib_ino_info_t *ino_p)
4640Sstevel@tonic-gate {
4650Sstevel@tonic-gate ASSERT(IB_IS_OBIO_INO(ino) || ino_p->ino_slot_no < 8);
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate if (IB_IS_OBIO_INO(ino))
4682973Sgovinda return (ino_p->ino_ipil_size);
4690Sstevel@tonic-gate else
4700Sstevel@tonic-gate return (--ib_p->ib_map_reg_counters[ino_p->ino_slot_no]);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /*ARGSUSED*/
4740Sstevel@tonic-gate void
pci_pbm_intr_dist(pbm_t * pbm_p)4750Sstevel@tonic-gate pci_pbm_intr_dist(pbm_t *pbm_p)
4760Sstevel@tonic-gate {
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate uintptr_t
pci_ib_setup(ib_t * ib_p)4800Sstevel@tonic-gate pci_ib_setup(ib_t *ib_p)
4810Sstevel@tonic-gate {
4820Sstevel@tonic-gate pci_t *pci_p = ib_p->ib_pci_p;
4830Sstevel@tonic-gate uintptr_t a = get_reg_base(pci_p);
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate ib_p->ib_ign = PCI_ID_TO_IGN(pci_p->pci_id);
4860Sstevel@tonic-gate ib_p->ib_max_ino = PSYCHO_MAX_INO;
4870Sstevel@tonic-gate ib_p->ib_slot_intr_map_regs = a + PSYCHO_IB_SLOT_INTR_MAP_REG_OFFSET;
4880Sstevel@tonic-gate ib_p->ib_obio_intr_map_regs = a + PSYCHO_IB_OBIO_INTR_MAP_REG_OFFSET;
4890Sstevel@tonic-gate ib_p->ib_obio_clear_intr_regs =
4900Sstevel@tonic-gate a + PSYCHO_IB_OBIO_CLEAR_INTR_REG_OFFSET;
4910Sstevel@tonic-gate return (a);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate uint32_t
pci_xlate_intr(dev_info_t * dip,dev_info_t * rdip,ib_t * ib_p,uint32_t intr)4950Sstevel@tonic-gate pci_xlate_intr(dev_info_t *dip, dev_info_t *rdip, ib_t *ib_p, uint32_t intr)
4960Sstevel@tonic-gate {
4970Sstevel@tonic-gate int32_t len;
4980Sstevel@tonic-gate dev_info_t *cdip;
4990Sstevel@tonic-gate pci_regspec_t *pci_rp;
5000Sstevel@tonic-gate uint32_t bus, dev, phys_hi;
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate if ((intr > PCI_INTD) || (intr < PCI_INTA))
5030Sstevel@tonic-gate goto done;
5040Sstevel@tonic-gate if (ddi_prop_exists(DDI_DEV_T_ANY, rdip, NULL, "interrupt-map"))
5050Sstevel@tonic-gate goto done;
5060Sstevel@tonic-gate /*
5070Sstevel@tonic-gate * Hack for pre 1275 imap machines e.g. quark & tazmo
5080Sstevel@tonic-gate * We need to turn any PCI interrupts into ino interrupts. machines
5090Sstevel@tonic-gate * supporting imap will have this done in the map.
5100Sstevel@tonic-gate */
5110Sstevel@tonic-gate cdip = get_my_childs_dip(dip, rdip);
5120Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, "reg",
5130Sstevel@tonic-gate (caddr_t)&pci_rp, &len) != DDI_SUCCESS)
5140Sstevel@tonic-gate return (0);
5150Sstevel@tonic-gate phys_hi = pci_rp->pci_phys_hi;
5160Sstevel@tonic-gate kmem_free(pci_rp, len);
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate bus = PCI_REG_BUS_G(phys_hi);
5190Sstevel@tonic-gate dev = PCI_REG_DEV_G(phys_hi);
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate * The ino for a given device id is derived as 0BSSNN where
5230Sstevel@tonic-gate *
5240Sstevel@tonic-gate * B = 0 for bus A, 1 for bus B
5250Sstevel@tonic-gate * SS = dev - 1 for bus A, dev - 2 for bus B
5260Sstevel@tonic-gate * NN = 00 for INTA#, 01 for INTB#, 10 for INTC#, 11 for INTD#
5270Sstevel@tonic-gate *
5280Sstevel@tonic-gate * if pci bus number > 0x80, then devices are located on the A side(66)
5290Sstevel@tonic-gate */
5300Sstevel@tonic-gate DEBUG3(DBG_IB, dip, "pci_xlate_intr: bus=%x, dev=%x, intr=%x\n",
5310Sstevel@tonic-gate bus, dev, intr);
5320Sstevel@tonic-gate intr--;
5330Sstevel@tonic-gate intr |= (bus & 0x80) ? ((dev - 1) << 2) : (0x10 | ((dev - 2) << 2));
5340Sstevel@tonic-gate
5350Sstevel@tonic-gate DEBUG1(DBG_IB, dip, "pci_xlate_intr: done ino=%x\n", intr);
5360Sstevel@tonic-gate done:
5370Sstevel@tonic-gate return (IB_INO_TO_MONDO(ib_p, intr));
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate /*
5410Sstevel@tonic-gate * Return the cpuid to to be used for an ino. Psycho has special slot-cpu
5420Sstevel@tonic-gate * constraints on cpu assignment:
5430Sstevel@tonic-gate *
5440Sstevel@tonic-gate * On multi-function pci cards, functions have separate devinfo nodes and
5450Sstevel@tonic-gate * interrupts. Some pci support hardware, such as the psycho/pcipsy chip,
5460Sstevel@tonic-gate * control interrupt-to-cpu binding on a per pci-slot basis instead of per
5470Sstevel@tonic-gate * function. For hardware like this, if an interrupt for one function has
5480Sstevel@tonic-gate * already been directed to a particular cpu, we can't choose a different
5490Sstevel@tonic-gate * cpu for another function implemented in the same pci-slot - if we did
5500Sstevel@tonic-gate * we would be redirecting the first function too (which causes problems
5510Sstevel@tonic-gate * for consistent interrupt distribution).
5520Sstevel@tonic-gate *
5530Sstevel@tonic-gate * This function determines if there is already an established slot-oriented
5540Sstevel@tonic-gate * interrupt-to-cpu binding established, if there is then it returns that
5550Sstevel@tonic-gate * cpu. Otherwise a new cpu is selected by intr_dist_cpuid().
5560Sstevel@tonic-gate *
5570Sstevel@tonic-gate * The devinfo node we are trying to associate a cpu with is
5582973Sgovinda * ino_p->ino_ipil_p->ipil_ih_head->ih_dip.
5590Sstevel@tonic-gate */
5600Sstevel@tonic-gate uint32_t
pci_intr_dist_cpuid(ib_t * ib_p,ib_ino_info_t * ino_p)5610Sstevel@tonic-gate pci_intr_dist_cpuid(ib_t *ib_p, ib_ino_info_t *ino_p)
5620Sstevel@tonic-gate {
5632973Sgovinda dev_info_t *rdip = ino_p->ino_ipil_p->ipil_ih_head->ih_dip;
5640Sstevel@tonic-gate dev_info_t *prdip = ddi_get_parent(rdip);
5650Sstevel@tonic-gate ib_ino_info_t *sino_p;
5660Sstevel@tonic-gate dev_info_t *sdip;
5670Sstevel@tonic-gate dev_info_t *psdip;
5680Sstevel@tonic-gate char *buf1 = NULL, *buf2 = NULL;
5690Sstevel@tonic-gate char *s1, *s2, *s3;
5700Sstevel@tonic-gate int l2;
5710Sstevel@tonic-gate int cpu_id;
5720Sstevel@tonic-gate
5730Sstevel@tonic-gate /* must be psycho driver parent (not ebus) */
5740Sstevel@tonic-gate if (strcmp(ddi_driver_name(prdip), "pcipsy") != 0)
5750Sstevel@tonic-gate goto newcpu;
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate /*
5780Sstevel@tonic-gate * From PCI 1275 binding: 2.2.1.3 Unit Address representation:
5790Sstevel@tonic-gate * Since the "unit-number" is the address that appears in on Open
5800Sstevel@tonic-gate * Firmware 'device path', it follows that only the DD and DD,FF
5810Sstevel@tonic-gate * forms of the text representation can appear in a 'device path'.
5820Sstevel@tonic-gate *
5830Sstevel@tonic-gate * The rdip unit address is of the form "DD[,FF]". Define two
5840Sstevel@tonic-gate * unit address strings that represent same-slot use: "DD" and "DD,".
5850Sstevel@tonic-gate * The first compare uses strcmp, the second uses strncmp.
5860Sstevel@tonic-gate */
5870Sstevel@tonic-gate s1 = ddi_get_name_addr(rdip);
5880Sstevel@tonic-gate if (s1 == NULL)
5890Sstevel@tonic-gate goto newcpu;
5900Sstevel@tonic-gate
5910Sstevel@tonic-gate buf1 = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* strcmp */
5920Sstevel@tonic-gate buf2 = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* strncmp */
5930Sstevel@tonic-gate s1 = strcpy(buf1, s1);
5940Sstevel@tonic-gate s2 = strcpy(buf2, s1);
5950Sstevel@tonic-gate
5960Sstevel@tonic-gate s1 = strrchr(s1, ',');
5970Sstevel@tonic-gate if (s1) {
5980Sstevel@tonic-gate *s1 = '\0'; /* have "DD,FF" */
5990Sstevel@tonic-gate s1 = buf1; /* search via strcmp "DD" */
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate s2 = strrchr(s2, ',');
6020Sstevel@tonic-gate *(s2 + 1) = '\0';
6030Sstevel@tonic-gate s2 = buf2;
6040Sstevel@tonic-gate l2 = strlen(s2); /* search via strncmp "DD," */
6050Sstevel@tonic-gate } else {
6060Sstevel@tonic-gate (void) strcat(s2, ","); /* have "DD" */
6070Sstevel@tonic-gate l2 = strlen(s2); /* search via strncmp "DD," */
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate /*
6110Sstevel@tonic-gate * Search the established ino list for devinfo nodes bound
6120Sstevel@tonic-gate * to an ino that matches one of the slot use strings.
6130Sstevel@tonic-gate */
6140Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex));
6152973Sgovinda for (sino_p = ib_p->ib_ino_lst; sino_p; sino_p = sino_p->ino_next_p) {
6160Sstevel@tonic-gate /* skip self and non-established */
6170Sstevel@tonic-gate if ((sino_p == ino_p) || (sino_p->ino_established == 0))
6180Sstevel@tonic-gate continue;
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate /* skip non-siblings */
6212973Sgovinda sdip = sino_p->ino_ipil_p->ipil_ih_head->ih_dip;
6220Sstevel@tonic-gate psdip = ddi_get_parent(sdip);
6230Sstevel@tonic-gate if (psdip != prdip)
6240Sstevel@tonic-gate continue;
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate /* must be psycho driver parent (not ebus) */
6270Sstevel@tonic-gate if (strcmp(ddi_driver_name(psdip), "pcipsy") != 0)
6280Sstevel@tonic-gate continue;
6290Sstevel@tonic-gate
6300Sstevel@tonic-gate s3 = ddi_get_name_addr(sdip);
6310Sstevel@tonic-gate if ((s1 && (strcmp(s1, s3) == 0)) ||
6320Sstevel@tonic-gate (strncmp(s2, s3, l2) == 0)) {
6330Sstevel@tonic-gate extern int intr_dist_debug;
6340Sstevel@tonic-gate
6350Sstevel@tonic-gate if (intr_dist_debug)
6360Sstevel@tonic-gate cmn_err(CE_CONT, "intr_dist: "
6370Sstevel@tonic-gate "pcipsy`pci_intr_dist_cpuid "
6380Sstevel@tonic-gate "%s#%d %s: cpu %d established "
6390Sstevel@tonic-gate "by %s#%d %s\n", ddi_driver_name(rdip),
6400Sstevel@tonic-gate ddi_get_instance(rdip),
6410Sstevel@tonic-gate ddi_deviname(rdip, buf1), sino_p->ino_cpuid,
6420Sstevel@tonic-gate ddi_driver_name(sdip),
6430Sstevel@tonic-gate ddi_get_instance(sdip),
6440Sstevel@tonic-gate ddi_deviname(sdip, buf2));
6450Sstevel@tonic-gate break;
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate }
6480Sstevel@tonic-gate
6490Sstevel@tonic-gate /* If a slot use match is found then use established cpu */
6500Sstevel@tonic-gate if (sino_p) {
6510Sstevel@tonic-gate cpu_id = sino_p->ino_cpuid; /* target established cpu */
6520Sstevel@tonic-gate goto out;
6530Sstevel@tonic-gate }
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate newcpu: cpu_id = intr_dist_cpuid(); /* target new cpu */
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate out: if (buf1)
6580Sstevel@tonic-gate kmem_free(buf1, MAXNAMELEN);
6590Sstevel@tonic-gate if (buf2)
6600Sstevel@tonic-gate kmem_free(buf2, MAXNAMELEN);
6610Sstevel@tonic-gate return (cpu_id);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate /*ARGSUSED*/
6661924Sarutz static void
cb_thermal_timeout(void * arg)6671924Sarutz cb_thermal_timeout(void *arg)
6681924Sarutz {
6691924Sarutz do_shutdown();
6701924Sarutz
6711924Sarutz /*
6721924Sarutz * In case do_shutdown() fails to halt the system.
6731924Sarutz */
6741924Sarutz (void) timeout((void(*)(void *))power_down, NULL,
6751924Sarutz thermal_powerdown_delay * hz);
6761924Sarutz }
6771924Sarutz
6781924Sarutz /*
6791924Sarutz * High-level handler for psycho's CBNINTR_THERMAL interrupt.
6801924Sarutz *
6811924Sarutz * Use timeout(9f) to implement the core functionality so that the
6821924Sarutz * timeout(9f) function can sleep, if needed.
6831924Sarutz */
6841924Sarutz /*ARGSUSED*/
6850Sstevel@tonic-gate uint_t
cb_thermal_intr(caddr_t a)6860Sstevel@tonic-gate cb_thermal_intr(caddr_t a)
6870Sstevel@tonic-gate {
6880Sstevel@tonic-gate cmn_err(CE_WARN, "pci: Thermal warning detected!\n");
6890Sstevel@tonic-gate if (pci_thermal_intr_fatal) {
6901924Sarutz (void) timeout(cb_thermal_timeout, NULL, 0);
6910Sstevel@tonic-gate }
6920Sstevel@tonic-gate return (DDI_INTR_CLAIMED);
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate void
pci_cb_teardown(pci_t * pci_p)6960Sstevel@tonic-gate pci_cb_teardown(pci_t *pci_p)
6970Sstevel@tonic-gate {
6980Sstevel@tonic-gate cb_t *cb_p = pci_p->pci_cb_p;
6990Sstevel@tonic-gate uint32_t mondo;
7000Sstevel@tonic-gate
7010Sstevel@tonic-gate if (pci_p->pci_thermal_interrupt != -1) {
7020Sstevel@tonic-gate mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
7030Sstevel@tonic-gate pci_p->pci_inos[CBNINTR_THERMAL]);
7040Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7050Sstevel@tonic-gate
7060Sstevel@tonic-gate cb_disable_nintr(cb_p, CBNINTR_THERMAL, IB_INTR_WAIT);
7072973Sgovinda VERIFY(rem_ivintr(mondo, pci_pil[CBNINTR_THERMAL]) == 0);
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate #ifdef _STARFIRE
7100Sstevel@tonic-gate pc_ittrans_uninit(cb_p->cb_ittrans_cookie);
7110Sstevel@tonic-gate #endif /* _STARFIRE */
7120Sstevel@tonic-gate }
7130Sstevel@tonic-gate
7140Sstevel@tonic-gate int
cb_register_intr(pci_t * pci_p)7150Sstevel@tonic-gate cb_register_intr(pci_t *pci_p)
7160Sstevel@tonic-gate {
7170Sstevel@tonic-gate uint32_t mondo;
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate if (pci_p->pci_thermal_interrupt == -1)
7200Sstevel@tonic-gate return (DDI_SUCCESS);
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
7230Sstevel@tonic-gate pci_p->pci_inos[CBNINTR_THERMAL]);
7240Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate VERIFY(add_ivintr(mondo, pci_pil[CBNINTR_THERMAL],
7272973Sgovinda (intrfunc)cb_thermal_intr, (caddr_t)pci_p->pci_cb_p,
7282973Sgovinda NULL, NULL) == 0);
7290Sstevel@tonic-gate
7300Sstevel@tonic-gate return (PCI_ATTACH_RETCODE(PCI_CB_OBJ, PCI_OBJ_INTR_ADD, DDI_SUCCESS));
7310Sstevel@tonic-gate }
7320Sstevel@tonic-gate
7330Sstevel@tonic-gate void
cb_enable_intr(pci_t * pci_p)7340Sstevel@tonic-gate cb_enable_intr(pci_t *pci_p)
7350Sstevel@tonic-gate {
7360Sstevel@tonic-gate if (pci_p->pci_thermal_interrupt != -1)
7370Sstevel@tonic-gate cb_enable_nintr(pci_p, CBNINTR_THERMAL);
7380Sstevel@tonic-gate }
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate uint64_t
cb_ino_to_map_pa(cb_t * cb_p,ib_ino_t ino)7410Sstevel@tonic-gate cb_ino_to_map_pa(cb_t *cb_p, ib_ino_t ino)
7420Sstevel@tonic-gate {
7430Sstevel@tonic-gate return (cb_p->cb_map_pa + ((ino & 0x1f) << 3));
7440Sstevel@tonic-gate }
7450Sstevel@tonic-gate
7460Sstevel@tonic-gate uint64_t
cb_ino_to_clr_pa(cb_t * cb_p,ib_ino_t ino)7470Sstevel@tonic-gate cb_ino_to_clr_pa(cb_t *cb_p, ib_ino_t ino)
7480Sstevel@tonic-gate {
7490Sstevel@tonic-gate return (cb_p->cb_clr_pa + ((ino & 0x1f) << 3));
7500Sstevel@tonic-gate }
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate /*
7530Sstevel@tonic-gate * allow removal of exported/shared thermal interrupt
7540Sstevel@tonic-gate */
7550Sstevel@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)7560Sstevel@tonic-gate cb_remove_xintr(pci_t *pci_p, dev_info_t *dip, dev_info_t *rdip,
7570Sstevel@tonic-gate ib_ino_t ino, ib_mondo_t mondo)
7580Sstevel@tonic-gate {
7590Sstevel@tonic-gate if (ino != pci_p->pci_inos[CBNINTR_THERMAL])
7600Sstevel@tonic-gate return (DDI_FAILURE);
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate cb_disable_nintr(pci_p->pci_cb_p, CBNINTR_THERMAL, IB_INTR_WAIT);
7632973Sgovinda VERIFY(rem_ivintr(mondo, pci_pil[CBNINTR_THERMAL]) == 0);
7640Sstevel@tonic-gate
7650Sstevel@tonic-gate DEBUG1(DBG_R_INTX, dip, "remove xintr %x\n", ino);
7660Sstevel@tonic-gate return (DDI_SUCCESS);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate int
pci_ecc_add_intr(pci_t * pci_p,int inum,ecc_intr_info_t * eii_p)7700Sstevel@tonic-gate pci_ecc_add_intr(pci_t *pci_p, int inum, ecc_intr_info_t *eii_p)
7710Sstevel@tonic-gate {
7720Sstevel@tonic-gate uint32_t mondo;
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
7750Sstevel@tonic-gate pci_p->pci_inos[inum]);
7760Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7770Sstevel@tonic-gate
7782973Sgovinda VERIFY(add_ivintr(mondo, pci_pil[inum], (intrfunc)ecc_intr,
7792973Sgovinda (caddr_t)eii_p, NULL, NULL) == 0);
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate return (PCI_ATTACH_RETCODE(PCI_ECC_OBJ, PCI_OBJ_INTR_ADD, DDI_SUCCESS));
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate void
pci_ecc_rem_intr(pci_t * pci_p,int inum,ecc_intr_info_t * eii_p)7850Sstevel@tonic-gate pci_ecc_rem_intr(pci_t *pci_p, int inum, ecc_intr_info_t *eii_p)
7860Sstevel@tonic-gate {
7870Sstevel@tonic-gate uint32_t mondo;
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
7900Sstevel@tonic-gate pci_p->pci_inos[inum]);
7910Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo);
7920Sstevel@tonic-gate
7932973Sgovinda VERIFY(rem_ivintr(mondo, pci_pil[inum]) == 0);
7940Sstevel@tonic-gate }
7950Sstevel@tonic-gate
7960Sstevel@tonic-gate static int pbm_has_pass_1_cheerio(pci_t *pci_p);
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate void
pbm_configure(pbm_t * pbm_p)7990Sstevel@tonic-gate pbm_configure(pbm_t *pbm_p)
8000Sstevel@tonic-gate {
8010Sstevel@tonic-gate pci_t *pci_p = pbm_p->pbm_pci_p;
8020Sstevel@tonic-gate cb_t *cb_p = pci_p->pci_cb_p;
8030Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip;
8040Sstevel@tonic-gate int instance = ddi_get_instance(dip);
8050Sstevel@tonic-gate uint32_t mask = 1 << instance;
8060Sstevel@tonic-gate uint64_t l;
8070Sstevel@tonic-gate uint16_t s = 0;
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate /*
8100Sstevel@tonic-gate * Workarounds for hardware bugs:
8110Sstevel@tonic-gate *
8120Sstevel@tonic-gate * bus parking
8130Sstevel@tonic-gate *
8140Sstevel@tonic-gate * Pass 2 psycho parts have a bug that requires bus
8150Sstevel@tonic-gate * parking to be disabled.
8160Sstevel@tonic-gate *
8170Sstevel@tonic-gate * Pass 1 cheerio parts have a bug which prevents them
8180Sstevel@tonic-gate * from working on a PBM with bus parking enabled.
8190Sstevel@tonic-gate *
8200Sstevel@tonic-gate * rerun disable
8210Sstevel@tonic-gate *
8220Sstevel@tonic-gate * Pass 1 and 2 psycho's require that the rerun's be
8230Sstevel@tonic-gate * enabled.
8240Sstevel@tonic-gate *
8250Sstevel@tonic-gate * retry limit
8260Sstevel@tonic-gate *
8270Sstevel@tonic-gate * For pass 1 and pass 2 psycho parts we disable the
8280Sstevel@tonic-gate * retry limit. This is because the limit of 16 seems
8290Sstevel@tonic-gate * too restrictive for devices that are children of pci
8300Sstevel@tonic-gate * to pci bridges. For pass 3 this limit will be 64.
8310Sstevel@tonic-gate *
8320Sstevel@tonic-gate * DMA write/PIO read sync
8330Sstevel@tonic-gate *
8340Sstevel@tonic-gate * For pass 2 psycho, the disable this feature.
8350Sstevel@tonic-gate */
8360Sstevel@tonic-gate l = lddphysio(cb_p->cb_base_pa + PSYCHO_CB_CONTROL_STATUS_REG_OFFSET);
8370Sstevel@tonic-gate l &= PSYCHO_CB_CONTROL_STATUS_VER;
8380Sstevel@tonic-gate l >>= PSYCHO_CB_CONTROL_STATUS_VER_SHIFT;
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate DEBUG2(DBG_ATTACH, dip, "cb_create: ver=%d, mask=%x\n", l, mask);
8410Sstevel@tonic-gate pci_rerun_disable = (uint32_t)-1;
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate switch (l) {
8440Sstevel@tonic-gate case 0:
8450Sstevel@tonic-gate DEBUG0(DBG_ATTACH, dip, "cb_create: psycho pass 1\n");
8460Sstevel@tonic-gate if (!pci_disable_pass1_workarounds) {
8470Sstevel@tonic-gate if (pbm_has_pass_1_cheerio(pci_p))
8480Sstevel@tonic-gate pci_bus_parking_enable &= ~mask;
8490Sstevel@tonic-gate pci_rerun_disable &= ~mask;
8500Sstevel@tonic-gate pci_retry_disable |= mask;
8510Sstevel@tonic-gate }
8520Sstevel@tonic-gate break;
8530Sstevel@tonic-gate case 1:
8540Sstevel@tonic-gate if (!pci_disable_pass2_workarounds) {
8550Sstevel@tonic-gate pci_bus_parking_enable &= ~mask;
8560Sstevel@tonic-gate pci_rerun_disable &= ~mask;
8570Sstevel@tonic-gate pci_retry_disable |= mask;
8580Sstevel@tonic-gate pci_dwsync_disable |= mask;
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate break;
8610Sstevel@tonic-gate case 2:
8620Sstevel@tonic-gate if (!pci_disable_pass3_workarounds) {
8630Sstevel@tonic-gate pci_dwsync_disable |= mask;
8640Sstevel@tonic-gate if (pbm_has_pass_1_cheerio(pci_p))
8650Sstevel@tonic-gate pci_bus_parking_enable &= ~mask;
8660Sstevel@tonic-gate }
8670Sstevel@tonic-gate break;
8680Sstevel@tonic-gate case 3:
8690Sstevel@tonic-gate if (!pci_disable_plus_workarounds) {
8700Sstevel@tonic-gate pci_dwsync_disable |= mask;
8710Sstevel@tonic-gate if (pbm_has_pass_1_cheerio(pci_p))
8720Sstevel@tonic-gate pci_bus_parking_enable &= ~mask;
8730Sstevel@tonic-gate }
8740Sstevel@tonic-gate break;
8750Sstevel@tonic-gate default:
8760Sstevel@tonic-gate if (!pci_disable_default_workarounds) {
8770Sstevel@tonic-gate pci_dwsync_disable |= mask;
8780Sstevel@tonic-gate if (pbm_has_pass_1_cheerio(pci_p))
8790Sstevel@tonic-gate pci_bus_parking_enable &= ~mask;
8800Sstevel@tonic-gate }
8810Sstevel@tonic-gate break;
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate /*
8850Sstevel@tonic-gate * Clear any PBM errors.
8860Sstevel@tonic-gate */
8870Sstevel@tonic-gate l = (PSYCHO_PCI_AFSR_E_MASK << PSYCHO_PCI_AFSR_PE_SHIFT) |
8880Sstevel@tonic-gate (PSYCHO_PCI_AFSR_E_MASK << PSYCHO_PCI_AFSR_SE_SHIFT);
8890Sstevel@tonic-gate *pbm_p->pbm_async_flt_status_reg = l;
8900Sstevel@tonic-gate
8910Sstevel@tonic-gate /*
8920Sstevel@tonic-gate * Clear error bits in configuration status register.
8930Sstevel@tonic-gate */
8940Sstevel@tonic-gate s = PCI_STAT_PERROR | PCI_STAT_S_PERROR |
8950Sstevel@tonic-gate PCI_STAT_R_MAST_AB | PCI_STAT_R_TARG_AB |
8960Sstevel@tonic-gate PCI_STAT_S_TARG_AB | PCI_STAT_S_PERROR;
8970Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf status reg=%x\n", s);
8980Sstevel@tonic-gate pbm_p->pbm_config_header->ch_status_reg = s;
8990Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf status reg==%x\n",
9000Sstevel@tonic-gate pbm_p->pbm_config_header->ch_status_reg);
9010Sstevel@tonic-gate
9020Sstevel@tonic-gate l = *pbm_p->pbm_ctrl_reg; /* save control register state */
9030Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: ctrl reg==%llx\n", l);
9040Sstevel@tonic-gate
9050Sstevel@tonic-gate /*
9060Sstevel@tonic-gate * See if any SERR# signals are asserted. We'll clear them later.
9070Sstevel@tonic-gate */
9080Sstevel@tonic-gate if (l & COMMON_PCI_CTRL_SERR)
9090Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: SERR asserted on pci bus\n",
9100Sstevel@tonic-gate ddi_driver_name(dip), instance);
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate /*
9130Sstevel@tonic-gate * Determine if PCI bus is running at 33 or 66 mhz.
9140Sstevel@tonic-gate */
9150Sstevel@tonic-gate if (l & COMMON_PCI_CTRL_SPEED)
9160Sstevel@tonic-gate pbm_p->pbm_speed = PBM_SPEED_66MHZ;
9170Sstevel@tonic-gate else
9180Sstevel@tonic-gate pbm_p->pbm_speed = PBM_SPEED_33MHZ;
9190Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: %d mhz\n",
9200Sstevel@tonic-gate pbm_p->pbm_speed == PBM_SPEED_66MHZ ? 66 : 33);
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate /*
9230Sstevel@tonic-gate * Enable error interrupts.
9240Sstevel@tonic-gate */
9250Sstevel@tonic-gate if (pci_error_intr_enable & mask)
9260Sstevel@tonic-gate l |= PSYCHO_PCI_CTRL_ERR_INT_EN;
9270Sstevel@tonic-gate else
9280Sstevel@tonic-gate l &= ~PSYCHO_PCI_CTRL_ERR_INT_EN;
9290Sstevel@tonic-gate
9300Sstevel@tonic-gate /*
9310Sstevel@tonic-gate * Disable pci streaming byte errors and error interrupts.
9320Sstevel@tonic-gate */
9330Sstevel@tonic-gate pci_sbh_error_intr_enable &= ~mask;
9340Sstevel@tonic-gate l &= ~PSYCHO_PCI_CTRL_SBH_INT_EN;
9350Sstevel@tonic-gate
9360Sstevel@tonic-gate /*
9370Sstevel@tonic-gate * Enable/disable bus parking.
9380Sstevel@tonic-gate */
9390Sstevel@tonic-gate if ((pci_bus_parking_enable & mask) &&
9400Sstevel@tonic-gate !ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
9410Sstevel@tonic-gate "no-bus-parking"))
9420Sstevel@tonic-gate l |= PSYCHO_PCI_CTRL_ARB_PARK;
9430Sstevel@tonic-gate else
9440Sstevel@tonic-gate l &= ~PSYCHO_PCI_CTRL_ARB_PARK;
9450Sstevel@tonic-gate
9460Sstevel@tonic-gate /*
9470Sstevel@tonic-gate * Enable arbitration.
9480Sstevel@tonic-gate */
9490Sstevel@tonic-gate if (pci_p->pci_side == B)
9500Sstevel@tonic-gate l = (l & ~PSYCHO_PCI_CTRL_ARB_EN_MASK) | pci_b_arb_enable;
9510Sstevel@tonic-gate else
9520Sstevel@tonic-gate l = (l & ~PSYCHO_PCI_CTRL_ARB_EN_MASK) | pci_a_arb_enable;
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate /*
9550Sstevel@tonic-gate * Make sure SERR is clear
9560Sstevel@tonic-gate */
9570Sstevel@tonic-gate l |= COMMON_PCI_CTRL_SERR;
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate /*
9600Sstevel@tonic-gate * Make sure power management interrupt is disabled.
9610Sstevel@tonic-gate */
9620Sstevel@tonic-gate l &= ~PSYCHO_PCI_CTRL_WAKEUP_EN;
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate #ifdef _STARFIRE
9650Sstevel@tonic-gate /*
9660Sstevel@tonic-gate * Hack to determine whether we do Starfire special handling
9670Sstevel@tonic-gate * For starfire, we simply program a constant odd-value
9680Sstevel@tonic-gate * (0x1D) in the MID field.
9690Sstevel@tonic-gate *
9700Sstevel@tonic-gate * Zero out the MID field before ORing. We leave the LSB of
9710Sstevel@tonic-gate * the MID field intact since we cannot have a zero (even)
9720Sstevel@tonic-gate * MID value.
9730Sstevel@tonic-gate */
9740Sstevel@tonic-gate l &= 0xFF0FFFFFFFFFFFFFULL;
9750Sstevel@tonic-gate l |= 0x1DULL << 51;
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate /*
9780Sstevel@tonic-gate * Program in the Interrupt Group Number. Here we have to
9790Sstevel@tonic-gate * convert the starfire 7bit upaid into a 5bit value.
9800Sstevel@tonic-gate */
9810Sstevel@tonic-gate l |= (uint64_t)STARFIRE_UPAID2HWIGN(pbm_p->pbm_pci_p->pci_id)
9820Sstevel@tonic-gate << COMMON_CB_CONTROL_STATUS_IGN_SHIFT;
9830Sstevel@tonic-gate #endif /* _STARFIRE */
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate /*
9860Sstevel@tonic-gate * Now finally write the control register with the appropriate value.
9870Sstevel@tonic-gate */
9880Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: ctrl reg=%llx\n", l);
9890Sstevel@tonic-gate *pbm_p->pbm_ctrl_reg = l;
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate /*
9920Sstevel@tonic-gate * Allow the diag register to be set based upon variable that
9930Sstevel@tonic-gate * can be configured via /etc/system.
9940Sstevel@tonic-gate */
9950Sstevel@tonic-gate l = *pbm_p->pbm_diag_reg;
9960Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: PCI diag reg==%llx\n", l);
9970Sstevel@tonic-gate if (pci_retry_disable & mask)
9980Sstevel@tonic-gate l |= COMMON_PCI_DIAG_DIS_RETRY;
9990Sstevel@tonic-gate if (pci_retry_enable & mask)
10000Sstevel@tonic-gate l &= ~COMMON_PCI_DIAG_DIS_RETRY;
10010Sstevel@tonic-gate if (pci_intsync_disable & mask)
10020Sstevel@tonic-gate l |= COMMON_PCI_DIAG_DIS_INTSYNC;
10030Sstevel@tonic-gate else
10040Sstevel@tonic-gate l &= ~COMMON_PCI_DIAG_DIS_INTSYNC;
10050Sstevel@tonic-gate if (pci_dwsync_disable & mask)
10060Sstevel@tonic-gate l |= PSYCHO_PCI_DIAG_DIS_DWSYNC;
10070Sstevel@tonic-gate else
10080Sstevel@tonic-gate l &= ~PSYCHO_PCI_DIAG_DIS_DWSYNC;
10090Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: PCI diag reg=%llx\n", l);
10100Sstevel@tonic-gate *pbm_p->pbm_diag_reg = l;
10110Sstevel@tonic-gate
10120Sstevel@tonic-gate /*
10130Sstevel@tonic-gate * Enable SERR# and parity reporting via command register.
10140Sstevel@tonic-gate */
10150Sstevel@tonic-gate s = pci_perr_enable & mask ? PCI_COMM_PARITY_DETECT : 0;
10160Sstevel@tonic-gate s |= pci_serr_enable & mask ? PCI_COMM_SERR_ENABLE : 0;
10170Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf command reg=%x\n", s);
10180Sstevel@tonic-gate pbm_p->pbm_config_header->ch_command_reg = s;
10190Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip, "pbm_configure: conf command reg==%x\n",
10200Sstevel@tonic-gate pbm_p->pbm_config_header->ch_command_reg);
10210Sstevel@tonic-gate
10220Sstevel@tonic-gate /*
10230Sstevel@tonic-gate * The current versions of the obp are suppose to set the latency
10240Sstevel@tonic-gate * timer register but do not. Bug 1234181 is open against this
10250Sstevel@tonic-gate * problem. Until this bug is fixed we check to see if the obp
10260Sstevel@tonic-gate * has attempted to set the latency timer register by checking
10270Sstevel@tonic-gate * for the existence of a "latency-timer" property.
10280Sstevel@tonic-gate */
10290Sstevel@tonic-gate if (pci_set_latency_timer_register) {
10300Sstevel@tonic-gate DEBUG1(DBG_ATTACH, dip,
10310Sstevel@tonic-gate "pbm_configure: set psycho latency timer to %x\n",
10320Sstevel@tonic-gate pci_latency_timer);
10330Sstevel@tonic-gate pbm_p->pbm_config_header->ch_latency_timer_reg =
10340Sstevel@tonic-gate pci_latency_timer;
10350Sstevel@tonic-gate }
10360Sstevel@tonic-gate
10370Sstevel@tonic-gate (void) ndi_prop_update_int(DDI_DEV_T_ANY, dip, "latency-timer",
10380Sstevel@tonic-gate (int)pbm_p->pbm_config_header->ch_latency_timer_reg);
10390Sstevel@tonic-gate }
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate uint_t
pbm_disable_pci_errors(pbm_t * pbm_p)10420Sstevel@tonic-gate pbm_disable_pci_errors(pbm_t *pbm_p)
10430Sstevel@tonic-gate {
10440Sstevel@tonic-gate pci_t *pci_p = pbm_p->pbm_pci_p;
10450Sstevel@tonic-gate ib_t *ib_p = pci_p->pci_ib_p;
10460Sstevel@tonic-gate
10470Sstevel@tonic-gate /*
10480Sstevel@tonic-gate * Disable error and streaming byte hole interrupts via the
10490Sstevel@tonic-gate * PBM control register.
10500Sstevel@tonic-gate */
10510Sstevel@tonic-gate *pbm_p->pbm_ctrl_reg &=
10520Sstevel@tonic-gate ~(PSYCHO_PCI_CTRL_ERR_INT_EN | PSYCHO_PCI_CTRL_SBH_INT_EN);
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate /*
10550Sstevel@tonic-gate * Disable error interrupts via the interrupt mapping register.
10560Sstevel@tonic-gate */
10570Sstevel@tonic-gate ib_intr_disable(ib_p, pci_p->pci_inos[CBNINTR_PBM], IB_INTR_NOWAIT);
10580Sstevel@tonic-gate return (BF_NONE);
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate /*ARGSUSED*/
10620Sstevel@tonic-gate uint64_t
pci_sc_configure(pci_t * pci_p)10630Sstevel@tonic-gate pci_sc_configure(pci_t *pci_p)
10640Sstevel@tonic-gate {
10650Sstevel@tonic-gate return (0);
10660Sstevel@tonic-gate }
10670Sstevel@tonic-gate
10680Sstevel@tonic-gate /*ARGSUSED*/
10690Sstevel@tonic-gate void
pci_pbm_dma_sync(pbm_t * pbm_p,ib_ino_t ino)10700Sstevel@tonic-gate pci_pbm_dma_sync(pbm_t *pbm_p, ib_ino_t ino)
10710Sstevel@tonic-gate {
10720Sstevel@tonic-gate uint64_t pa = pbm_p->pbm_sync_reg_pa;
10730Sstevel@tonic-gate if (pa)
10740Sstevel@tonic-gate (void) lddphysio(pa); /* Load from Sync Register */
10750Sstevel@tonic-gate }
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate /*ARGSUSED*/
10780Sstevel@tonic-gate dvma_context_t
pci_iommu_get_dvma_context(iommu_t * iommu_p,dvma_addr_t dvma_pg_index)10790Sstevel@tonic-gate pci_iommu_get_dvma_context(iommu_t *iommu_p, dvma_addr_t dvma_pg_index)
10800Sstevel@tonic-gate {
10810Sstevel@tonic-gate ASSERT(0);
10820Sstevel@tonic-gate return (0);
10830Sstevel@tonic-gate }
10840Sstevel@tonic-gate
10850Sstevel@tonic-gate /*ARGSUSED*/
10860Sstevel@tonic-gate void
pci_iommu_free_dvma_context(iommu_t * iommu_p,dvma_context_t ctx)10870Sstevel@tonic-gate pci_iommu_free_dvma_context(iommu_t *iommu_p, dvma_context_t ctx)
10880Sstevel@tonic-gate {
10890Sstevel@tonic-gate ASSERT(0);
10900Sstevel@tonic-gate }
10910Sstevel@tonic-gate
10920Sstevel@tonic-gate void
pci_iommu_config(iommu_t * iommu_p,uint64_t iommu_ctl,uint64_t cfgpa)10930Sstevel@tonic-gate pci_iommu_config(iommu_t *iommu_p, uint64_t iommu_ctl, uint64_t cfgpa)
10940Sstevel@tonic-gate {
10950Sstevel@tonic-gate volatile uint64_t *pbm_csr_p = (volatile uint64_t *)
10960Sstevel@tonic-gate get_pbm_reg_base(iommu_p->iommu_pci_p);
10970Sstevel@tonic-gate volatile uint64_t pbm_ctl = *pbm_csr_p;
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate volatile uint64_t *iommu_ctl_p = iommu_p->iommu_ctrl_reg;
11000Sstevel@tonic-gate volatile uint64_t tsb_bar_val = iommu_p->iommu_tsb_paddr;
11010Sstevel@tonic-gate volatile uint64_t *tsb_bar_p = iommu_p->iommu_tsb_base_addr_reg;
11020Sstevel@tonic-gate
11030Sstevel@tonic-gate DEBUG2(DBG_ATTACH, iommu_p->iommu_pci_p->pci_dip,
11040Sstevel@tonic-gate "\npci_iommu_config: pbm_csr_p=%016llx pbm_ctl=%016llx",
11050Sstevel@tonic-gate pbm_csr_p, pbm_ctl);
11060Sstevel@tonic-gate DEBUG2(DBG_ATTACH|DBG_CONT, iommu_p->iommu_pci_p->pci_dip,
11070Sstevel@tonic-gate "\n\tiommu_ctl_p=%016llx iommu_ctl=%016llx",
11080Sstevel@tonic-gate iommu_ctl_p, iommu_ctl);
11090Sstevel@tonic-gate DEBUG2(DBG_ATTACH|DBG_CONT, iommu_p->iommu_pci_p->pci_dip,
11100Sstevel@tonic-gate "\n\tcfgpa=%016llx tsb_bar_val=%016llx", cfgpa, tsb_bar_val);
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate if (!cfgpa)
11130Sstevel@tonic-gate goto reprog;
11140Sstevel@tonic-gate
11150Sstevel@tonic-gate /* disable PBM arbiters - turn off bits 0-7 */
11160Sstevel@tonic-gate *pbm_csr_p = (pbm_ctl >> 8) << 8;
11170Sstevel@tonic-gate
11180Sstevel@tonic-gate /* make sure we own the bus by reading any child device config space */
11190Sstevel@tonic-gate (void) ldphysio(cfgpa); /* also flushes the prev write */
11200Sstevel@tonic-gate reprog:
11210Sstevel@tonic-gate *tsb_bar_p = tsb_bar_val;
11220Sstevel@tonic-gate *iommu_ctl_p = iommu_ctl;
11230Sstevel@tonic-gate
11240Sstevel@tonic-gate *pbm_csr_p = pbm_ctl; /* re-enable bus arbitration */
11250Sstevel@tonic-gate pbm_ctl = *pbm_csr_p; /* flush all prev writes */
11260Sstevel@tonic-gate }
11270Sstevel@tonic-gate
11280Sstevel@tonic-gate int
pci_sc_ctx_inv(dev_info_t * dip,sc_t * sc_p,ddi_dma_impl_t * mp)11290Sstevel@tonic-gate pci_sc_ctx_inv(dev_info_t *dip, sc_t *sc_p, ddi_dma_impl_t *mp)
11300Sstevel@tonic-gate {
11310Sstevel@tonic-gate ASSERT(0);
11320Sstevel@tonic-gate return (DDI_FAILURE);
11330Sstevel@tonic-gate }
11340Sstevel@tonic-gate
11350Sstevel@tonic-gate void
pci_cb_setup(pci_t * pci_p)11360Sstevel@tonic-gate pci_cb_setup(pci_t *pci_p)
11370Sstevel@tonic-gate {
11380Sstevel@tonic-gate uint64_t csr, csr_pa, pa;
11390Sstevel@tonic-gate cb_t *cb_p = pci_p->pci_cb_p;
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate /* cb_p->cb_node_id = 0; */
11420Sstevel@tonic-gate cb_p->cb_ign = PCI_ID_TO_IGN(pci_p->pci_id);
11430Sstevel@tonic-gate pa = (uint64_t)hat_getpfnum(kas.a_hat, pci_p->pci_address[0]);
11440Sstevel@tonic-gate cb_p->cb_base_pa = pa = pa >> (32 - MMU_PAGESHIFT) << 32;
11450Sstevel@tonic-gate cb_p->cb_map_pa = pa + PSYCHO_IB_OBIO_INTR_MAP_REG_OFFSET;
11460Sstevel@tonic-gate cb_p->cb_clr_pa = pa + PSYCHO_IB_OBIO_CLEAR_INTR_REG_OFFSET;
11470Sstevel@tonic-gate cb_p->cb_obsta_pa = pa + COMMON_IB_OBIO_INTR_STATE_DIAG_REG;
11480Sstevel@tonic-gate
11490Sstevel@tonic-gate csr_pa = pa + PSYCHO_CB_CONTROL_STATUS_REG_OFFSET;
11500Sstevel@tonic-gate csr = lddphysio(csr_pa);
11510Sstevel@tonic-gate
11520Sstevel@tonic-gate /*
11530Sstevel@tonic-gate * Clear any pending address parity errors.
11540Sstevel@tonic-gate */
11550Sstevel@tonic-gate if (csr & COMMON_CB_CONTROL_STATUS_APERR) {
11560Sstevel@tonic-gate csr |= COMMON_CB_CONTROL_STATUS_APERR;
11570Sstevel@tonic-gate cmn_err(CE_WARN, "clearing UPA address parity error\n");
11580Sstevel@tonic-gate }
11590Sstevel@tonic-gate csr |= COMMON_CB_CONTROL_STATUS_APCKEN;
11600Sstevel@tonic-gate csr &= ~COMMON_CB_CONTROL_STATUS_IAP;
11610Sstevel@tonic-gate stdphysio(csr_pa, csr);
11620Sstevel@tonic-gate
11630Sstevel@tonic-gate #ifdef _STARFIRE
11640Sstevel@tonic-gate /* Setup Starfire interrupt target translation */
11650Sstevel@tonic-gate pc_ittrans_init(pci_p->pci_id, &cb_p->cb_ittrans_cookie);
11660Sstevel@tonic-gate #endif /* _STARFIRE */
11670Sstevel@tonic-gate
11680Sstevel@tonic-gate }
11690Sstevel@tonic-gate
11700Sstevel@tonic-gate void
pci_ecc_setup(ecc_t * ecc_p)11710Sstevel@tonic-gate pci_ecc_setup(ecc_t *ecc_p)
11720Sstevel@tonic-gate {
11730Sstevel@tonic-gate ecc_p->ecc_ue.ecc_errpndg_mask = 0;
11740Sstevel@tonic-gate ecc_p->ecc_ue.ecc_offset_mask = PSYCHO_ECC_UE_AFSR_DW_OFFSET;
11750Sstevel@tonic-gate ecc_p->ecc_ue.ecc_offset_shift = PSYCHO_ECC_UE_AFSR_DW_OFFSET_SHIFT;
11760Sstevel@tonic-gate ecc_p->ecc_ue.ecc_size_log2 = 3;
11770Sstevel@tonic-gate
11780Sstevel@tonic-gate ecc_p->ecc_ce.ecc_errpndg_mask = 0;
11790Sstevel@tonic-gate ecc_p->ecc_ce.ecc_offset_mask = PSYCHO_ECC_CE_AFSR_DW_OFFSET;
11800Sstevel@tonic-gate ecc_p->ecc_ce.ecc_offset_shift = PSYCHO_ECC_CE_AFSR_DW_OFFSET_SHIFT;
11810Sstevel@tonic-gate ecc_p->ecc_ce.ecc_size_log2 = 3;
11820Sstevel@tonic-gate }
11830Sstevel@tonic-gate
11840Sstevel@tonic-gate /*
11850Sstevel@tonic-gate * overwrite dvma end address (only on virtual-dma systems)
11860Sstevel@tonic-gate * initialize tsb size
11870Sstevel@tonic-gate * reset context bits
11880Sstevel@tonic-gate * return: IOMMU CSR bank base address (VA)
11890Sstevel@tonic-gate */
11900Sstevel@tonic-gate uintptr_t
pci_iommu_setup(iommu_t * iommu_p)11910Sstevel@tonic-gate pci_iommu_setup(iommu_t *iommu_p)
11920Sstevel@tonic-gate {
11930Sstevel@tonic-gate pci_dvma_range_prop_t *dvma_prop;
11940Sstevel@tonic-gate int dvma_prop_len;
11950Sstevel@tonic-gate
11960Sstevel@tonic-gate pci_t *pci_p = iommu_p->iommu_pci_p;
11970Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip;
11980Sstevel@tonic-gate uint_t tsb_size = iommu_tsb_cookie_to_size(pci_p->pci_tsb_cookie);
11990Sstevel@tonic-gate uint_t tsb_size_prop;
12000Sstevel@tonic-gate
12010Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
12020Sstevel@tonic-gate "virtual-dma", (caddr_t)&dvma_prop, &dvma_prop_len) !=
12030Sstevel@tonic-gate DDI_PROP_SUCCESS)
12040Sstevel@tonic-gate goto tsb_done;
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate if (dvma_prop_len != sizeof (pci_dvma_range_prop_t)) {
12070Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: invalid virtual-dma property",
12080Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
12090Sstevel@tonic-gate goto tsb_end;
12100Sstevel@tonic-gate }
12110Sstevel@tonic-gate iommu_p->iommu_dvma_end = dvma_prop->dvma_base +
12120Sstevel@tonic-gate (dvma_prop->dvma_len - 1);
12130Sstevel@tonic-gate tsb_size_prop = IOMMU_BTOP(dvma_prop->dvma_len) * sizeof (uint64_t);
12140Sstevel@tonic-gate tsb_size = MIN(tsb_size_prop, tsb_size);
12150Sstevel@tonic-gate tsb_end:
12160Sstevel@tonic-gate kmem_free(dvma_prop, dvma_prop_len);
12170Sstevel@tonic-gate tsb_done:
12180Sstevel@tonic-gate iommu_p->iommu_tsb_size = iommu_tsb_size_encode(tsb_size);
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate if (CHIP_TYPE(pci_p) != PCI_CHIP_HUMMINGBIRD)
12210Sstevel@tonic-gate pci_preserve_iommu_tsb = 0;
12220Sstevel@tonic-gate
12230Sstevel@tonic-gate /*
12240Sstevel@tonic-gate * Psycho has no context support.
12250Sstevel@tonic-gate */
12260Sstevel@tonic-gate iommu_p->iommu_ctx_bitmap = NULL;
12270Sstevel@tonic-gate iommu_p->iommu_flush_ctx_reg = NULL;
12280Sstevel@tonic-gate pci_use_contexts = 0;
12290Sstevel@tonic-gate pci_sc_use_contexts = 0;
12300Sstevel@tonic-gate
12310Sstevel@tonic-gate /*
12320Sstevel@tonic-gate * Determine the virtual address of the register block
12330Sstevel@tonic-gate * containing the iommu control registers.
12340Sstevel@tonic-gate */
12350Sstevel@tonic-gate return (get_reg_base(pci_p));
12360Sstevel@tonic-gate }
12370Sstevel@tonic-gate
12380Sstevel@tonic-gate /*ARGSUSED*/
12390Sstevel@tonic-gate void
pci_iommu_teardown(iommu_t * iommu_p)12400Sstevel@tonic-gate pci_iommu_teardown(iommu_t *iommu_p)
12410Sstevel@tonic-gate {
12420Sstevel@tonic-gate }
12430Sstevel@tonic-gate
12440Sstevel@tonic-gate /* The psycho+ PBM reg base is at 1fe.0000.2000 */
12450Sstevel@tonic-gate uintptr_t
get_pbm_reg_base(pci_t * pci_p)12460Sstevel@tonic-gate get_pbm_reg_base(pci_t *pci_p)
12470Sstevel@tonic-gate {
12480Sstevel@tonic-gate return ((uintptr_t)(pci_p->pci_address[0] +
12490Sstevel@tonic-gate (pci_stream_buf_exists ? 0 : PSYCHO_PCI_PBM_REG_BASE)));
12500Sstevel@tonic-gate }
12510Sstevel@tonic-gate
12520Sstevel@tonic-gate void
pci_post_uninit_child(pci_t * pci_p)12530Sstevel@tonic-gate pci_post_uninit_child(pci_t *pci_p)
12540Sstevel@tonic-gate {
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate void
pci_pbm_setup(pbm_t * pbm_p)12580Sstevel@tonic-gate pci_pbm_setup(pbm_t *pbm_p)
12590Sstevel@tonic-gate {
12600Sstevel@tonic-gate pci_t *pci_p = pbm_p->pbm_pci_p;
12610Sstevel@tonic-gate
12620Sstevel@tonic-gate /*
12630Sstevel@tonic-gate * Get the base virtual address for the PBM control block.
12640Sstevel@tonic-gate */
12650Sstevel@tonic-gate uintptr_t a = get_pbm_reg_base(pci_p);
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate /*
12680Sstevel@tonic-gate * Get the virtual address of the PCI configuration header.
12690Sstevel@tonic-gate * This should be mapped little-endian.
12700Sstevel@tonic-gate */
12710Sstevel@tonic-gate pbm_p->pbm_config_header =
12720Sstevel@tonic-gate (config_header_t *)get_config_reg_base(pci_p);
12730Sstevel@tonic-gate
12740Sstevel@tonic-gate /*
12750Sstevel@tonic-gate * Get the virtual addresses for control, error and diag
12760Sstevel@tonic-gate * registers.
12770Sstevel@tonic-gate */
12780Sstevel@tonic-gate pbm_p->pbm_ctrl_reg = (uint64_t *)(a + PSYCHO_PCI_CTRL_REG_OFFSET);
12790Sstevel@tonic-gate pbm_p->pbm_diag_reg = (uint64_t *)(a + PSYCHO_PCI_DIAG_REG_OFFSET);
12800Sstevel@tonic-gate pbm_p->pbm_async_flt_status_reg =
12810Sstevel@tonic-gate (uint64_t *)(a + PSYCHO_PCI_ASYNC_FLT_STATUS_REG_OFFSET);
12820Sstevel@tonic-gate pbm_p->pbm_async_flt_addr_reg =
12830Sstevel@tonic-gate (uint64_t *)(a + PSYCHO_PCI_ASYNC_FLT_ADDR_REG_OFFSET);
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate if (CHIP_TYPE(pci_p) >= PCI_CHIP_SABRE)
12860Sstevel@tonic-gate pbm_p->pbm_sync_reg_pa =
12870Sstevel@tonic-gate pci_p->pci_cb_p->cb_base_pa + DMA_WRITE_SYNC_REG;
12880Sstevel@tonic-gate }
12890Sstevel@tonic-gate
12900Sstevel@tonic-gate /*ARGSUSED*/
12910Sstevel@tonic-gate void
pci_pbm_teardown(pbm_t * pbm_p)12920Sstevel@tonic-gate pci_pbm_teardown(pbm_t *pbm_p)
12930Sstevel@tonic-gate {
12940Sstevel@tonic-gate }
12950Sstevel@tonic-gate
12960Sstevel@tonic-gate void
pci_sc_setup(sc_t * sc_p)12970Sstevel@tonic-gate pci_sc_setup(sc_t *sc_p)
12980Sstevel@tonic-gate {
12990Sstevel@tonic-gate pci_t *pci_p = sc_p->sc_pci_p;
13000Sstevel@tonic-gate
13010Sstevel@tonic-gate /*
13020Sstevel@tonic-gate * Determine the virtual addresses of the streaming cache
13030Sstevel@tonic-gate * control/status and flush registers.
13040Sstevel@tonic-gate */
13050Sstevel@tonic-gate uintptr_t a = get_pbm_reg_base(pci_p);
13060Sstevel@tonic-gate sc_p->sc_ctrl_reg = (uint64_t *)(a + PSYCHO_SC_CTRL_REG_OFFSET);
13070Sstevel@tonic-gate sc_p->sc_invl_reg = (uint64_t *)(a + PSYCHO_SC_INVL_REG_OFFSET);
13080Sstevel@tonic-gate sc_p->sc_sync_reg = (uint64_t *)(a + PSYCHO_SC_SYNC_REG_OFFSET);
13090Sstevel@tonic-gate
13100Sstevel@tonic-gate /*
13110Sstevel@tonic-gate * Determine the virtual addresses of the streaming cache
13120Sstevel@tonic-gate * diagnostic access registers.
13130Sstevel@tonic-gate */
13140Sstevel@tonic-gate a = get_reg_base(pci_p);
13150Sstevel@tonic-gate if (pci_p->pci_bus_range.lo != 0) {
13160Sstevel@tonic-gate sc_p->sc_data_diag_acc = (uint64_t *)
13170Sstevel@tonic-gate (a + PSYCHO_SC_A_DATA_DIAG_OFFSET);
13180Sstevel@tonic-gate sc_p->sc_tag_diag_acc = (uint64_t *)
13190Sstevel@tonic-gate (a + PSYCHO_SC_A_TAG_DIAG_OFFSET);
13200Sstevel@tonic-gate sc_p->sc_ltag_diag_acc = (uint64_t *)
13210Sstevel@tonic-gate (a + PSYCHO_SC_A_LTAG_DIAG_OFFSET);
13220Sstevel@tonic-gate } else {
13230Sstevel@tonic-gate sc_p->sc_data_diag_acc = (uint64_t *)
13240Sstevel@tonic-gate (a + PSYCHO_SC_B_DATA_DIAG_OFFSET);
13250Sstevel@tonic-gate sc_p->sc_tag_diag_acc = (uint64_t *)
13260Sstevel@tonic-gate (a + PSYCHO_SC_B_TAG_DIAG_OFFSET);
13270Sstevel@tonic-gate sc_p->sc_ltag_diag_acc = (uint64_t *)
13280Sstevel@tonic-gate (a + PSYCHO_SC_B_LTAG_DIAG_OFFSET);
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate }
13310Sstevel@tonic-gate
13320Sstevel@tonic-gate int
pci_get_numproxy(dev_info_t * dip)13330Sstevel@tonic-gate pci_get_numproxy(dev_info_t *dip)
13340Sstevel@tonic-gate {
13350Sstevel@tonic-gate return (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
13360Sstevel@tonic-gate "#upa-interrupt-proxies", 1));
13370Sstevel@tonic-gate }
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate int
pci_get_portid(dev_info_t * dip)13400Sstevel@tonic-gate pci_get_portid(dev_info_t *dip)
13410Sstevel@tonic-gate {
13420Sstevel@tonic-gate return (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
13430Sstevel@tonic-gate "upa-portid", -1));
13440Sstevel@tonic-gate }
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate /*
13470Sstevel@tonic-gate * pbm_has_pass_1_cheerio
13480Sstevel@tonic-gate *
13490Sstevel@tonic-gate *
13500Sstevel@tonic-gate * Given a PBM soft state pointer, this routine scans it child nodes
13510Sstevel@tonic-gate * to see if one is a pass 1 cheerio.
13520Sstevel@tonic-gate *
13530Sstevel@tonic-gate * return value: 1 if pass 1 cheerio is found, 0 otherwise
13540Sstevel@tonic-gate */
13550Sstevel@tonic-gate static int
pbm_has_pass_1_cheerio(pci_t * pci_p)13560Sstevel@tonic-gate pbm_has_pass_1_cheerio(pci_t *pci_p)
13570Sstevel@tonic-gate {
13580Sstevel@tonic-gate dev_info_t *cdip;
13590Sstevel@tonic-gate int found = 0;
13600Sstevel@tonic-gate char *s;
13610Sstevel@tonic-gate int rev;
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate cdip = ddi_get_child(pci_p->pci_dip);
13640Sstevel@tonic-gate while (cdip != NULL && found == 0) {
13650Sstevel@tonic-gate s = ddi_get_name(cdip);
13660Sstevel@tonic-gate if (strcmp(s, "ebus") == 0 || strcmp(s, "pci108e,1000") == 0) {
13670Sstevel@tonic-gate rev =
13680Sstevel@tonic-gate ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
13690Sstevel@tonic-gate "revision-id", 0);
13700Sstevel@tonic-gate if (rev == 0)
13710Sstevel@tonic-gate found = 1;
13720Sstevel@tonic-gate }
13730Sstevel@tonic-gate cdip = ddi_get_next_sibling(cdip);
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate return (found);
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate
13780Sstevel@tonic-gate /*
13790Sstevel@tonic-gate * Psycho Performance Events.
13800Sstevel@tonic-gate */
13810Sstevel@tonic-gate pci_kev_mask_t
13820Sstevel@tonic-gate psycho_pci_events[] = {
13830Sstevel@tonic-gate {"dvma_stream_rd_a", 0x0}, {"dvma_stream_wr_a", 0x1},
13840Sstevel@tonic-gate {"dvma_const_rd_a", 0x2}, {"dvma_const_wr_a", 0x3},
13850Sstevel@tonic-gate {"dvma_stream_buf_mis_a", 0x4}, {"dvma_cycles_a", 0x5},
13860Sstevel@tonic-gate {"dvma_wd_xfr_a", 0x6}, {"pio_cycles_a", 0x7},
13870Sstevel@tonic-gate {"dvma_stream_rd_b", 0x8}, {"dvma_stream_wr_b", 0x9},
13880Sstevel@tonic-gate {"dvma_const_rd_b", 0xa}, {"dvma_const_wr_b", 0xb},
13890Sstevel@tonic-gate {"dvma_stream_buf_mis_b", 0xc}, {"dvma_cycles_b", 0xd},
13900Sstevel@tonic-gate {"dvma_wd_xfr_b", 0xe}, {"pio_cycles_b", 0xf},
13910Sstevel@tonic-gate {"dvma_tlb_misses", 0x10}, {"interrupts", 0x11},
13920Sstevel@tonic-gate {"upa_inter_nack", 0x12}, {"pio_reads", 0x13},
13930Sstevel@tonic-gate {"pio_writes", 0x14}, {"merge_buffer", 0x15},
13940Sstevel@tonic-gate {"dma_tbwalk_a", 0x16}, {"dma_stc_a", 0x17},
13950Sstevel@tonic-gate {"dma_tbwalk_b", 0x18}, {"dma_stc_b", 0x19},
13960Sstevel@tonic-gate {"clear_pic", 0x1f}
13970Sstevel@tonic-gate };
13980Sstevel@tonic-gate
13990Sstevel@tonic-gate /*
14000Sstevel@tonic-gate * Create the picN kstat's.
14010Sstevel@tonic-gate */
14020Sstevel@tonic-gate void
pci_kstat_init()14030Sstevel@tonic-gate pci_kstat_init()
14040Sstevel@tonic-gate {
14050Sstevel@tonic-gate pci_name_kstat = (pci_ksinfo_t *)kmem_alloc(sizeof (pci_ksinfo_t),
14060Sstevel@tonic-gate KM_NOSLEEP);
14070Sstevel@tonic-gate
14080Sstevel@tonic-gate if (pci_name_kstat == NULL) {
14090Sstevel@tonic-gate cmn_err(CE_WARN, "pcipsy : no space for kstat\n");
14100Sstevel@tonic-gate } else {
14110Sstevel@tonic-gate pci_name_kstat->pic_no_evs =
14120Sstevel@tonic-gate sizeof (psycho_pci_events) / sizeof (pci_kev_mask_t);
14130Sstevel@tonic-gate pci_name_kstat->pic_shift[0] = PSYCHO_SHIFT_PIC0;
14140Sstevel@tonic-gate pci_name_kstat->pic_shift[1] = PSYCHO_SHIFT_PIC1;
14150Sstevel@tonic-gate pci_create_name_kstat("pcip",
14160Sstevel@tonic-gate pci_name_kstat, psycho_pci_events);
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate }
14190Sstevel@tonic-gate
14200Sstevel@tonic-gate /*
14210Sstevel@tonic-gate * Called from _fini()
14220Sstevel@tonic-gate */
14230Sstevel@tonic-gate void
pci_kstat_fini()14240Sstevel@tonic-gate pci_kstat_fini()
14250Sstevel@tonic-gate {
14260Sstevel@tonic-gate if (pci_name_kstat != NULL) {
14270Sstevel@tonic-gate pci_delete_name_kstat(pci_name_kstat);
14280Sstevel@tonic-gate kmem_free(pci_name_kstat, sizeof (pci_ksinfo_t));
14290Sstevel@tonic-gate pci_name_kstat = NULL;
14300Sstevel@tonic-gate }
14310Sstevel@tonic-gate }
14320Sstevel@tonic-gate
14330Sstevel@tonic-gate /* ARGSUSED */
14340Sstevel@tonic-gate void
pci_add_pci_kstat(pci_t * pci_p)14350Sstevel@tonic-gate pci_add_pci_kstat(pci_t *pci_p)
14360Sstevel@tonic-gate {
14370Sstevel@tonic-gate }
14380Sstevel@tonic-gate
14390Sstevel@tonic-gate /* ARGSUSED */
14400Sstevel@tonic-gate void
pci_rem_pci_kstat(pci_t * pci_p)14410Sstevel@tonic-gate pci_rem_pci_kstat(pci_t *pci_p)
14420Sstevel@tonic-gate {
14430Sstevel@tonic-gate }
14440Sstevel@tonic-gate
14450Sstevel@tonic-gate /*
14460Sstevel@tonic-gate * Create the performance 'counters' kstat.
14470Sstevel@tonic-gate */
14480Sstevel@tonic-gate void
pci_add_upstream_kstat(pci_t * pci_p)14490Sstevel@tonic-gate pci_add_upstream_kstat(pci_t *pci_p)
14500Sstevel@tonic-gate {
14510Sstevel@tonic-gate pci_common_t *cmn_p = pci_p->pci_common_p;
14520Sstevel@tonic-gate pci_cntr_pa_t *cntr_pa_p = &cmn_p->pci_cmn_uks_pa;
14530Sstevel@tonic-gate uint64_t regbase = va_to_pa((void *)get_reg_base(pci_p));
14540Sstevel@tonic-gate
14550Sstevel@tonic-gate cntr_pa_p->pcr_pa = regbase + PSYCHO_PERF_PCR_OFFSET;
14560Sstevel@tonic-gate cntr_pa_p->pic_pa = regbase + PSYCHO_PERF_PIC_OFFSET;
14570Sstevel@tonic-gate cmn_p->pci_common_uksp = pci_create_cntr_kstat(pci_p, "pcip",
14580Sstevel@tonic-gate NUM_OF_PICS, pci_cntr_kstat_pa_update, cntr_pa_p);
14590Sstevel@tonic-gate }
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate /*
14620Sstevel@tonic-gate * Extract the drivers binding name to identify which chip
14630Sstevel@tonic-gate * we're binding to. Whenever a new bus bridge is created, the driver alias
14640Sstevel@tonic-gate * entry should be added here to identify the device if needed. If a device
14650Sstevel@tonic-gate * isn't added, the identity defaults to PCI_CHIP_UNIDENTIFIED.
14660Sstevel@tonic-gate */
14670Sstevel@tonic-gate static uint32_t
pci_identity_init(pci_t * pci_p)14680Sstevel@tonic-gate pci_identity_init(pci_t *pci_p)
14690Sstevel@tonic-gate {
14700Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip;
14710Sstevel@tonic-gate char *name = ddi_binding_name(dip);
14720Sstevel@tonic-gate
14730Sstevel@tonic-gate if (strcmp(name, "pci108e,8000") == 0)
14740Sstevel@tonic-gate return (CHIP_ID(PCI_CHIP_PSYCHO, 0x00, 0x00));
14750Sstevel@tonic-gate if (strcmp(name, "pci108e,a000") == 0)
14760Sstevel@tonic-gate return (CHIP_ID(PCI_CHIP_SABRE, 0x00, 0x00));
14770Sstevel@tonic-gate if (strcmp(name, "pci108e,a001") == 0)
14780Sstevel@tonic-gate return (CHIP_ID(PCI_CHIP_HUMMINGBIRD, 0x00, 0x00));
14790Sstevel@tonic-gate cmn_err(CE_CONT, "?%s%d:using default chip identity\n",
14800Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip));
14810Sstevel@tonic-gate return (CHIP_ID(PCI_CHIP_PSYCHO, 0x00, 0x00));
14820Sstevel@tonic-gate }
14830Sstevel@tonic-gate
14840Sstevel@tonic-gate /*ARGSUSED*/
14850Sstevel@tonic-gate void
pci_post_init_child(pci_t * pci_p,dev_info_t * child)14860Sstevel@tonic-gate pci_post_init_child(pci_t *pci_p, dev_info_t *child)
14870Sstevel@tonic-gate {
14880Sstevel@tonic-gate }
14890Sstevel@tonic-gate
14900Sstevel@tonic-gate /*ARGSUSED*/
14910Sstevel@tonic-gate int
pci_pbm_add_intr(pci_t * pci_p)14920Sstevel@tonic-gate pci_pbm_add_intr(pci_t *pci_p)
14930Sstevel@tonic-gate {
14940Sstevel@tonic-gate return (DDI_SUCCESS);
14950Sstevel@tonic-gate }
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate /*ARGSUSED*/
14980Sstevel@tonic-gate void
pci_pbm_rem_intr(pci_t * pci_p)14990Sstevel@tonic-gate pci_pbm_rem_intr(pci_t *pci_p)
15000Sstevel@tonic-gate {
15010Sstevel@tonic-gate }
15020Sstevel@tonic-gate
15030Sstevel@tonic-gate /*ARGSUSED*/
15040Sstevel@tonic-gate void
pci_pbm_suspend(pci_t * pci_p)15050Sstevel@tonic-gate pci_pbm_suspend(pci_t *pci_p)
15060Sstevel@tonic-gate {
15070Sstevel@tonic-gate }
15080Sstevel@tonic-gate
15090Sstevel@tonic-gate /*ARGSUSED*/
15100Sstevel@tonic-gate void
pci_pbm_resume(pci_t * pci_p)15110Sstevel@tonic-gate pci_pbm_resume(pci_t *pci_p)
15120Sstevel@tonic-gate {
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate /*
15160Sstevel@tonic-gate * pcipsy error handling 101:
15170Sstevel@tonic-gate *
15180Sstevel@tonic-gate * The various functions below are responsible for error handling. Given
15190Sstevel@tonic-gate * a particular error, they must gather the appropriate state, report all
15200Sstevel@tonic-gate * errors with correct payload, and attempt recovery where ever possible.
15210Sstevel@tonic-gate *
15220Sstevel@tonic-gate * Recovery in the context of this driver is being able notify a leaf device
15230Sstevel@tonic-gate * of the failed transaction. This leaf device may either be the master or
15240Sstevel@tonic-gate * target for this transaction and may have already received an error
15250Sstevel@tonic-gate * notification via a PCI interrupt. Notification is done via DMA and access
15260Sstevel@tonic-gate * handles. If we capture an address for the transaction then we can map it
15270Sstevel@tonic-gate * to a handle(if the leaf device is fma-compliant) and fault the handle as
15280Sstevel@tonic-gate * well as call the device driver registered callback.
15290Sstevel@tonic-gate *
15300Sstevel@tonic-gate * The hardware can either interrupt or trap upon detection of an error, in
15310Sstevel@tonic-gate * some rare cases it also causes a fatal reset.
15320Sstevel@tonic-gate *
15330Sstevel@tonic-gate * pbm_error_intr() and ecc_intr() are responsible for PCI Block Module
15340Sstevel@tonic-gate * errors(generic PCI + bridge specific) and ECC errors, respectively. They
15350Sstevel@tonic-gate * are common between pcisch and pcipsy and therefore exist in pci_pbm.c and
15360Sstevel@tonic-gate * pci_ecc.c. To support error handling certain chip specific handlers
15370Sstevel@tonic-gate * must exist and they are defined below.
15380Sstevel@tonic-gate *
15390Sstevel@tonic-gate * cpu_deferred_error() and cpu_async_error(), handle the traps that may
15400Sstevel@tonic-gate * have originated from IO space. They call into the registered IO callbacks
15410Sstevel@tonic-gate * to report and handle errors that may have caused the trap.
15420Sstevel@tonic-gate *
15430Sstevel@tonic-gate * pci_pbm_err_handler() is called by pbm_error_intr() or pci_err_callback()
15440Sstevel@tonic-gate * (generic fma callback for pcipsy/pcisch, pci_fm.c). pci_err_callback() is
15450Sstevel@tonic-gate * called when the CPU has trapped because of a possible IO error(TO/BERR/UE).
15460Sstevel@tonic-gate * It will call pci_pbm_err_handler() to report and handle all PCI/PBM/IOMMU
15470Sstevel@tonic-gate * related errors which are detected by the chip.
15480Sstevel@tonic-gate *
15490Sstevel@tonic-gate * pci_pbm_err_handler() calls a generic interface pbm_afsr_report()(pci_pbm.c)
15500Sstevel@tonic-gate * to report the pbm specific errors and attempt to map the failed address
15510Sstevel@tonic-gate * (if captured) to a device instance. pbm_afsr_report() calls a chip specific
15520Sstevel@tonic-gate * interface to interpret the afsr bits pci_pbm_classify()(pcisch.c/pcipsy.c).
15530Sstevel@tonic-gate *
15540Sstevel@tonic-gate * ecc_err_handler()(pci_ecc.c) also calls a chip specific interface to
15550Sstevel@tonic-gate * interpret the afsr, pci_ecc_classify(). ecc_err_handler() also calls
15560Sstevel@tonic-gate * pci_pbm_err_handler() and ndi_fm_handler_dispatch() to log any related
15570Sstevel@tonic-gate * errors.
15580Sstevel@tonic-gate *
15590Sstevel@tonic-gate * To make sure that the trap code and the interrupt code are not going
15600Sstevel@tonic-gate * to step on each others toes we have a per chip pci_fm_mutex. This also
15610Sstevel@tonic-gate * makes it necessary for us to be cautious while we are at a high PIL, so
15620Sstevel@tonic-gate * that we do not cause a subsequent trap that causes us to hang.
15630Sstevel@tonic-gate *
15640Sstevel@tonic-gate * The attempt to commonize code was meant to keep in line with the current
15650Sstevel@tonic-gate * pci driver implementation and it was not meant to confuse. If you are
15660Sstevel@tonic-gate * confused then don't worry, I was too.
15670Sstevel@tonic-gate */
15680Sstevel@tonic-gate
15690Sstevel@tonic-gate /*
15700Sstevel@tonic-gate * For Psycho, a UE is always fatal, except if it is a translation error on a
15710Sstevel@tonic-gate * Darwin platform. We ignore these because they do not cause data corruption.
15720Sstevel@tonic-gate */
15730Sstevel@tonic-gate int
ecc_ue_is_fatal(struct async_flt * ecc)15740Sstevel@tonic-gate ecc_ue_is_fatal(struct async_flt *ecc)
15750Sstevel@tonic-gate {
15760Sstevel@tonic-gate return (((uint_t)(ecc->flt_stat >> SABRE_UE_AFSR_PDTE_SHIFT) &
15770Sstevel@tonic-gate SABRE_UE_AFSR_E_PDTE) == 0);
15780Sstevel@tonic-gate }
15790Sstevel@tonic-gate
15800Sstevel@tonic-gate /*
15810Sstevel@tonic-gate * pci_ecc_classify, called by ecc_handler to classify ecc errors
15820Sstevel@tonic-gate * and determine if we should panic or not.
15831817Sarutz *
15841817Sarutz * Note that it is possible yet extremely rare for more than one
15851817Sarutz * primary error bit to be set. We classify the ecc error based
15861817Sarutz * on the first set bit that is found.
15870Sstevel@tonic-gate */
15880Sstevel@tonic-gate void
pci_ecc_classify(uint64_t err,ecc_errstate_t * ecc_err_p)15890Sstevel@tonic-gate pci_ecc_classify(uint64_t err, ecc_errstate_t *ecc_err_p)
15900Sstevel@tonic-gate {
15910Sstevel@tonic-gate struct async_flt *ecc = &ecc_err_p->ecc_aflt;
15920Sstevel@tonic-gate pci_common_t *cmn_p = ecc_err_p->ecc_ii_p.ecc_p->ecc_pci_cmn_p;
15930Sstevel@tonic-gate
15940Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cmn_p->pci_fm_mutex));
15950Sstevel@tonic-gate
15960Sstevel@tonic-gate ecc_err_p->ecc_bridge_type = PCI_BRIDGE_TYPE(cmn_p);
15970Sstevel@tonic-gate /*
15980Sstevel@tonic-gate * Get the parent bus id that caused the error.
15990Sstevel@tonic-gate */
16000Sstevel@tonic-gate ecc_err_p->ecc_dev_id = (ecc_err_p->ecc_afsr & PSYCHO_ECC_UE_AFSR_ID)
16010Sstevel@tonic-gate >> PSYCHO_ECC_UE_AFSR_ID_SHIFT;
16020Sstevel@tonic-gate /*
16030Sstevel@tonic-gate * Determine the doubleword offset of the error.
16040Sstevel@tonic-gate */
16050Sstevel@tonic-gate ecc_err_p->ecc_dw_offset = (ecc_err_p->ecc_afsr &
16060Sstevel@tonic-gate PSYCHO_ECC_UE_AFSR_DW_OFFSET)
16070Sstevel@tonic-gate >> PSYCHO_ECC_UE_AFSR_DW_OFFSET_SHIFT;
16080Sstevel@tonic-gate /*
16090Sstevel@tonic-gate * Determine the primary error type.
16100Sstevel@tonic-gate */
1611*4039Skd93003 if (err & COMMON_ECC_AFSR_E_PIO) {
16120Sstevel@tonic-gate if (ecc_err_p->ecc_ii_p.ecc_type == CBNINTR_UE) {
16130Sstevel@tonic-gate if (ecc_err_p->ecc_pri) {
16140Sstevel@tonic-gate ecc->flt_erpt_class = PCI_ECC_PIO_UE;
16150Sstevel@tonic-gate } else {
16160Sstevel@tonic-gate ecc->flt_erpt_class = PCI_ECC_SEC_PIO_UE;
16170Sstevel@tonic-gate }
16180Sstevel@tonic-gate ecc->flt_panic = ecc_ue_is_fatal(&ecc_err_p->ecc_aflt);
16190Sstevel@tonic-gate } else {
16200Sstevel@tonic-gate ecc->flt_erpt_class = ecc_err_p->ecc_pri ?
16210Sstevel@tonic-gate PCI_ECC_PIO_CE : PCI_ECC_SEC_PIO_CE;
16220Sstevel@tonic-gate return;
16230Sstevel@tonic-gate }
1624*4039Skd93003 } else if (err & COMMON_ECC_AFSR_E_DRD) {
16250Sstevel@tonic-gate if (ecc_err_p->ecc_ii_p.ecc_type == CBNINTR_UE) {
16260Sstevel@tonic-gate if (ecc_err_p->ecc_pri) {
16270Sstevel@tonic-gate ecc->flt_erpt_class = PCI_ECC_DRD_UE;
16280Sstevel@tonic-gate } else {
16290Sstevel@tonic-gate ecc->flt_erpt_class = PCI_ECC_SEC_DRD_UE;
16300Sstevel@tonic-gate }
16310Sstevel@tonic-gate ecc->flt_panic = ecc_ue_is_fatal(&ecc_err_p->ecc_aflt);
16320Sstevel@tonic-gate } else {
16330Sstevel@tonic-gate ecc->flt_erpt_class = ecc_err_p->ecc_pri ?
16340Sstevel@tonic-gate PCI_ECC_DRD_CE : PCI_ECC_SEC_DRD_CE;
16350Sstevel@tonic-gate return;
16360Sstevel@tonic-gate }
1637*4039Skd93003 } else if (err & COMMON_ECC_AFSR_E_DWR) {
16380Sstevel@tonic-gate if (ecc_err_p->ecc_ii_p.ecc_type == CBNINTR_UE) {
16390Sstevel@tonic-gate if (ecc_err_p->ecc_pri) {
16400Sstevel@tonic-gate ecc->flt_erpt_class = PCI_ECC_DWR_UE;
16410Sstevel@tonic-gate } else {
16420Sstevel@tonic-gate ecc->flt_erpt_class = PCI_ECC_SEC_DWR_UE;
16430Sstevel@tonic-gate }
16440Sstevel@tonic-gate ecc->flt_panic = ecc_ue_is_fatal(&ecc_err_p->ecc_aflt);
16450Sstevel@tonic-gate } else {
16460Sstevel@tonic-gate ecc->flt_erpt_class = ecc_err_p->ecc_pri ?
16470Sstevel@tonic-gate PCI_ECC_DWR_CE : PCI_ECC_SEC_DWR_CE;
16480Sstevel@tonic-gate return;
16490Sstevel@tonic-gate }
16500Sstevel@tonic-gate }
16510Sstevel@tonic-gate }
16520Sstevel@tonic-gate
16530Sstevel@tonic-gate ushort_t
pci_ecc_get_synd(uint64_t afsr)16540Sstevel@tonic-gate pci_ecc_get_synd(uint64_t afsr)
16550Sstevel@tonic-gate {
16560Sstevel@tonic-gate return ((ushort_t)((afsr & PSYCHO_ECC_CE_AFSR_SYND)
16570Sstevel@tonic-gate >> PSYCHO_ECC_CE_AFSR_SYND_SHIFT));
16580Sstevel@tonic-gate }
16590Sstevel@tonic-gate
16600Sstevel@tonic-gate /*
16610Sstevel@tonic-gate * pci_pbm_classify, called by pbm_afsr_report to classify piow afsr.
16620Sstevel@tonic-gate */
16630Sstevel@tonic-gate int
pci_pbm_classify(pbm_errstate_t * pbm_err_p)16640Sstevel@tonic-gate pci_pbm_classify(pbm_errstate_t *pbm_err_p)
16650Sstevel@tonic-gate {
16660Sstevel@tonic-gate uint32_t e;
16670Sstevel@tonic-gate int nerr = 0;
16680Sstevel@tonic-gate char **tmp_class;
16690Sstevel@tonic-gate
16700Sstevel@tonic-gate if (pbm_err_p->pbm_pri) {
16710Sstevel@tonic-gate tmp_class = &pbm_err_p->pbm_pci.pci_err_class;
16720Sstevel@tonic-gate e = PBM_AFSR_TO_PRIERR(pbm_err_p->pbm_afsr);
16730Sstevel@tonic-gate pbm_err_p->pbm_log = FM_LOG_PCI;
16740Sstevel@tonic-gate } else {
16750Sstevel@tonic-gate tmp_class = &pbm_err_p->pbm_err_class;
16760Sstevel@tonic-gate e = PBM_AFSR_TO_SECERR(pbm_err_p->pbm_afsr);
16770Sstevel@tonic-gate pbm_err_p->pbm_log = FM_LOG_PBM;
16780Sstevel@tonic-gate }
16790Sstevel@tonic-gate
16800Sstevel@tonic-gate if (e & PSYCHO_PCI_AFSR_E_MA) {
16810Sstevel@tonic-gate *tmp_class = pbm_err_p->pbm_pri ? PCI_MA : PCI_SEC_MA;
16820Sstevel@tonic-gate nerr++;
16830Sstevel@tonic-gate }
16840Sstevel@tonic-gate if (e & PSYCHO_PCI_AFSR_E_TA) {
16850Sstevel@tonic-gate *tmp_class = pbm_err_p->pbm_pri ? PCI_REC_TA : PCI_SEC_REC_TA;
16860Sstevel@tonic-gate nerr++;
16870Sstevel@tonic-gate }
16880Sstevel@tonic-gate if (e & PSYCHO_PCI_AFSR_E_RTRY) {
16890Sstevel@tonic-gate pbm_err_p->pbm_err_class = pbm_err_p->pbm_pri ?
16901865Sdilpreet PCI_PBM_RETRY : PCI_SEC_PBM_RETRY;
16910Sstevel@tonic-gate pbm_err_p->pbm_log = FM_LOG_PBM;
16920Sstevel@tonic-gate nerr++;
16930Sstevel@tonic-gate }
16940Sstevel@tonic-gate if (e & PSYCHO_PCI_AFSR_E_PERR) {
16950Sstevel@tonic-gate *tmp_class = pbm_err_p->pbm_pri ? PCI_MDPE : PCI_SEC_MDPE;
16960Sstevel@tonic-gate nerr++;
16970Sstevel@tonic-gate }
16980Sstevel@tonic-gate return (nerr);
16990Sstevel@tonic-gate }
17000Sstevel@tonic-gate
17010Sstevel@tonic-gate /*
17020Sstevel@tonic-gate * Function used to clear PBM/PCI/IOMMU error state after error handling
17030Sstevel@tonic-gate * is complete. Only clearing error bits which have been logged. Called by
17040Sstevel@tonic-gate * pci_pbm_err_handler and pci_bus_exit.
17050Sstevel@tonic-gate */
17060Sstevel@tonic-gate static void
pci_clear_error(pci_t * pci_p,pbm_errstate_t * pbm_err_p)17070Sstevel@tonic-gate pci_clear_error(pci_t *pci_p, pbm_errstate_t *pbm_err_p)
17080Sstevel@tonic-gate {
17090Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p;
17100Sstevel@tonic-gate
17110Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pbm_p->pbm_pci_p->pci_common_p->pci_fm_mutex));
17120Sstevel@tonic-gate
17130Sstevel@tonic-gate *pbm_p->pbm_ctrl_reg = pbm_err_p->pbm_ctl_stat;
17140Sstevel@tonic-gate *pbm_p->pbm_async_flt_status_reg = pbm_err_p->pbm_afsr;
17150Sstevel@tonic-gate pbm_p->pbm_config_header->ch_status_reg =
17160Sstevel@tonic-gate pbm_err_p->pbm_pci.pci_cfg_stat;
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate /*ARGSUSED*/
17200Sstevel@tonic-gate int
pci_pbm_err_handler(dev_info_t * dip,ddi_fm_error_t * derr,const void * impl_data,int caller)17210Sstevel@tonic-gate pci_pbm_err_handler(dev_info_t *dip, ddi_fm_error_t *derr,
17220Sstevel@tonic-gate const void *impl_data, int caller)
17230Sstevel@tonic-gate {
17240Sstevel@tonic-gate int fatal = 0;
17250Sstevel@tonic-gate int nonfatal = 0;
17260Sstevel@tonic-gate int unknown = 0;
17270Sstevel@tonic-gate uint32_t prierr, secerr;
17280Sstevel@tonic-gate pbm_errstate_t pbm_err;
17290Sstevel@tonic-gate char buf[FM_MAX_CLASS];
17300Sstevel@tonic-gate pci_t *pci_p = (pci_t *)impl_data;
17310Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p;
17320Sstevel@tonic-gate int ret = 0;
17330Sstevel@tonic-gate uint64_t pbm_ctl_stat;
17340Sstevel@tonic-gate uint16_t pci_cfg_stat;
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pci_p->pci_common_p->pci_fm_mutex));
17370Sstevel@tonic-gate pci_pbm_errstate_get(pci_p, &pbm_err);
17380Sstevel@tonic-gate
17390Sstevel@tonic-gate derr->fme_ena = derr->fme_ena ? derr->fme_ena :
17400Sstevel@tonic-gate fm_ena_generate(0, FM_ENA_FMT1);
17410Sstevel@tonic-gate
17420Sstevel@tonic-gate prierr = PBM_AFSR_TO_PRIERR(pbm_err.pbm_afsr);
17430Sstevel@tonic-gate secerr = PBM_AFSR_TO_SECERR(pbm_err.pbm_afsr);
17440Sstevel@tonic-gate
17450Sstevel@tonic-gate if (derr->fme_flag == DDI_FM_ERR_EXPECTED) {
17460Sstevel@tonic-gate if (caller == PCI_TRAP_CALL) {
17470Sstevel@tonic-gate /*
17480Sstevel@tonic-gate * For ddi_caut_get treat all events as
17490Sstevel@tonic-gate * nonfatal. The trampoline will set
17500Sstevel@tonic-gate * err_ena = 0, err_status = NONFATAL. We only
17510Sstevel@tonic-gate * really call this function so that pci_clear_error()
17520Sstevel@tonic-gate * and ndi_fm_handler_dispatch() will get called.
17530Sstevel@tonic-gate */
17540Sstevel@tonic-gate derr->fme_status = DDI_FM_NONFATAL;
17550Sstevel@tonic-gate nonfatal++;
17560Sstevel@tonic-gate goto done;
17570Sstevel@tonic-gate } else {
17580Sstevel@tonic-gate /*
17590Sstevel@tonic-gate * For ddi_caut_put treat all events as nonfatal. Here
17600Sstevel@tonic-gate * we have the handle and can call ndi_fm_acc_err_set().
17610Sstevel@tonic-gate */
17620Sstevel@tonic-gate derr->fme_status = DDI_FM_NONFATAL;
17630Sstevel@tonic-gate ndi_fm_acc_err_set(pbm_p->pbm_excl_handle, derr);
17640Sstevel@tonic-gate nonfatal++;
17650Sstevel@tonic-gate goto done;
17660Sstevel@tonic-gate }
17670Sstevel@tonic-gate } else if (derr->fme_flag == DDI_FM_ERR_PEEK) {
17680Sstevel@tonic-gate /*
17690Sstevel@tonic-gate * For ddi_peek treat all events as nonfatal. We only
17700Sstevel@tonic-gate * really call this function so that pci_clear_error()
17710Sstevel@tonic-gate * and ndi_fm_handler_dispatch() will get called.
17720Sstevel@tonic-gate */
17730Sstevel@tonic-gate nonfatal++;
17740Sstevel@tonic-gate goto done;
17750Sstevel@tonic-gate } else if (derr->fme_flag == DDI_FM_ERR_POKE) {
17760Sstevel@tonic-gate /*
17770Sstevel@tonic-gate * For ddi_poke we can treat as nonfatal if the
17780Sstevel@tonic-gate * following conditions are met :
17790Sstevel@tonic-gate * 1. Make sure only primary error is MA/TA
17800Sstevel@tonic-gate * 2. Make sure no secondary error
17810Sstevel@tonic-gate * 3. check pci config header stat reg to see MA/TA is
17820Sstevel@tonic-gate * logged. We cannot verify only MA/TA is recorded
17830Sstevel@tonic-gate * since it gets much more complicated when a
17840Sstevel@tonic-gate * PCI-to-PCI bridge is present.
17850Sstevel@tonic-gate */
17860Sstevel@tonic-gate if ((prierr == PSYCHO_PCI_AFSR_E_MA) && !secerr &&
17870Sstevel@tonic-gate (pbm_err.pbm_pci.pci_cfg_stat & PCI_STAT_R_MAST_AB)) {
17880Sstevel@tonic-gate nonfatal++;
17890Sstevel@tonic-gate goto done;
17900Sstevel@tonic-gate }
17910Sstevel@tonic-gate if ((prierr == PSYCHO_PCI_AFSR_E_TA) && !secerr &&
17920Sstevel@tonic-gate (pbm_err.pbm_pci.pci_cfg_stat & PCI_STAT_R_TARG_AB)) {
17930Sstevel@tonic-gate nonfatal++;
17940Sstevel@tonic-gate goto done;
17950Sstevel@tonic-gate }
17960Sstevel@tonic-gate }
17970Sstevel@tonic-gate
17980Sstevel@tonic-gate if (prierr || secerr) {
17990Sstevel@tonic-gate ret = pbm_afsr_report(dip, derr->fme_ena, &pbm_err);
18000Sstevel@tonic-gate if (ret == DDI_FM_FATAL)
18010Sstevel@tonic-gate fatal++;
18020Sstevel@tonic-gate else
18030Sstevel@tonic-gate nonfatal++;
18040Sstevel@tonic-gate }
18050Sstevel@tonic-gate
18060Sstevel@tonic-gate ret = pci_cfg_report(dip, derr, &pbm_err.pbm_pci, caller, prierr);
18070Sstevel@tonic-gate if (ret == DDI_FM_FATAL)
18080Sstevel@tonic-gate fatal++;
18090Sstevel@tonic-gate else if (ret == DDI_FM_NONFATAL)
18100Sstevel@tonic-gate nonfatal++;
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate pbm_ctl_stat = pbm_err.pbm_ctl_stat;
18130Sstevel@tonic-gate pci_cfg_stat = pbm_err.pbm_pci.pci_cfg_stat;
18140Sstevel@tonic-gate
18150Sstevel@tonic-gate /*
18160Sstevel@tonic-gate * PBM Received System Error - During any transaction, or
18170Sstevel@tonic-gate * at any point on the bus, some device may detect a critical
18180Sstevel@tonic-gate * error and signal a system error to the system.
18190Sstevel@tonic-gate */
18200Sstevel@tonic-gate if (pbm_ctl_stat & COMMON_PCI_CTRL_SERR) {
18210Sstevel@tonic-gate /*
18220Sstevel@tonic-gate * may be expected (master abort from pci-pci bridge during
18230Sstevel@tonic-gate * poke will generate SERR)
18240Sstevel@tonic-gate */
18250Sstevel@tonic-gate if (derr->fme_flag != DDI_FM_ERR_POKE) {
18260Sstevel@tonic-gate pbm_err.pbm_pci.pci_err_class = PCI_REC_SERR;
18270Sstevel@tonic-gate (void) snprintf(buf, FM_MAX_CLASS, "%s.%s",
18280Sstevel@tonic-gate PCI_ERROR_SUBCLASS, pbm_err.pbm_pci.pci_err_class);
18290Sstevel@tonic-gate ddi_fm_ereport_post(dip, buf, derr->fme_ena,
18300Sstevel@tonic-gate DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, 0,
18310Sstevel@tonic-gate PCI_CONFIG_STATUS, DATA_TYPE_UINT16, pci_cfg_stat,
18320Sstevel@tonic-gate PCI_CONFIG_COMMAND, DATA_TYPE_UINT16,
18330Sstevel@tonic-gate pbm_err.pbm_pci.pci_cfg_comm, PCI_PA,
18340Sstevel@tonic-gate DATA_TYPE_UINT64, (uint64_t)0, NULL);
18350Sstevel@tonic-gate }
18361865Sdilpreet unknown++;
18370Sstevel@tonic-gate }
18380Sstevel@tonic-gate
18390Sstevel@tonic-gate /* Streaming Byte Hole Error */
18400Sstevel@tonic-gate if (pbm_ctl_stat & COMMON_PCI_CTRL_SBH_ERR) {
18410Sstevel@tonic-gate if (pci_panic_on_sbh_errors)
18420Sstevel@tonic-gate fatal++;
18430Sstevel@tonic-gate else
18440Sstevel@tonic-gate nonfatal++;
18450Sstevel@tonic-gate pbm_err.pbm_err_class = PCI_PSY_SBH;
18460Sstevel@tonic-gate pbm_ereport_post(dip, derr->fme_ena, &pbm_err);
18470Sstevel@tonic-gate }
18480Sstevel@tonic-gate done:
18490Sstevel@tonic-gate ret = ndi_fm_handler_dispatch(dip, NULL, derr);
18500Sstevel@tonic-gate if (ret == DDI_FM_FATAL) {
18510Sstevel@tonic-gate fatal++;
18520Sstevel@tonic-gate } else if (ret == DDI_FM_NONFATAL) {
18530Sstevel@tonic-gate nonfatal++;
18540Sstevel@tonic-gate } else if (ret == DDI_FM_UNKNOWN) {
18550Sstevel@tonic-gate unknown++;
18560Sstevel@tonic-gate }
18570Sstevel@tonic-gate
18580Sstevel@tonic-gate /*
18590Sstevel@tonic-gate * rserr not claimed as nonfatal by a child is treated as fatal
18600Sstevel@tonic-gate */
18611865Sdilpreet if (unknown && !nonfatal && !fatal)
18620Sstevel@tonic-gate fatal++;
18630Sstevel@tonic-gate
18640Sstevel@tonic-gate /* Cleanup and reset error bits */
18650Sstevel@tonic-gate pci_clear_error(pci_p, &pbm_err);
18660Sstevel@tonic-gate
18670Sstevel@tonic-gate return (fatal ? DDI_FM_FATAL : (nonfatal ? DDI_FM_NONFATAL :
18680Sstevel@tonic-gate (unknown ? DDI_FM_UNKNOWN : DDI_FM_OK)));
18690Sstevel@tonic-gate }
18700Sstevel@tonic-gate
18710Sstevel@tonic-gate int
pci_check_error(pci_t * pci_p)18720Sstevel@tonic-gate pci_check_error(pci_t *pci_p)
18730Sstevel@tonic-gate {
18740Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p;
18750Sstevel@tonic-gate uint16_t pci_cfg_stat;
18760Sstevel@tonic-gate uint64_t pbm_ctl_stat, pbm_afsr;
18770Sstevel@tonic-gate
18780Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pci_p->pci_common_p->pci_fm_mutex));
18790Sstevel@tonic-gate
18800Sstevel@tonic-gate pci_cfg_stat = pbm_p->pbm_config_header->ch_status_reg;
18810Sstevel@tonic-gate pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
18820Sstevel@tonic-gate pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
18830Sstevel@tonic-gate
18840Sstevel@tonic-gate if ((pci_cfg_stat & (PCI_STAT_S_PERROR | PCI_STAT_S_TARG_AB |
18850Sstevel@tonic-gate PCI_STAT_R_TARG_AB | PCI_STAT_R_MAST_AB |
18860Sstevel@tonic-gate PCI_STAT_S_SYSERR | PCI_STAT_PERROR)) ||
18870Sstevel@tonic-gate (pbm_ctl_stat & (COMMON_PCI_CTRL_SBH_ERR |
18880Sstevel@tonic-gate COMMON_PCI_CTRL_SERR)) ||
18890Sstevel@tonic-gate (PBM_AFSR_TO_PRIERR(pbm_afsr)))
18900Sstevel@tonic-gate return (1);
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate return (0);
18930Sstevel@tonic-gate
18940Sstevel@tonic-gate }
18950Sstevel@tonic-gate
18960Sstevel@tonic-gate /*
18970Sstevel@tonic-gate * Function used to gather PBM/PCI error state for the
18980Sstevel@tonic-gate * pci_pbm_err_handler. This function must be called while pci_fm_mutex
18990Sstevel@tonic-gate * is held.
19000Sstevel@tonic-gate */
19010Sstevel@tonic-gate static void
pci_pbm_errstate_get(pci_t * pci_p,pbm_errstate_t * pbm_err_p)19020Sstevel@tonic-gate pci_pbm_errstate_get(pci_t *pci_p, pbm_errstate_t *pbm_err_p)
19030Sstevel@tonic-gate {
19040Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p;
19050Sstevel@tonic-gate
19060Sstevel@tonic-gate ASSERT(MUTEX_HELD(&pci_p->pci_common_p->pci_fm_mutex));
19070Sstevel@tonic-gate bzero(pbm_err_p, sizeof (pbm_errstate_t));
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate /*
19100Sstevel@tonic-gate * Capture all pbm error state for later logging
19110Sstevel@tonic-gate */
19120Sstevel@tonic-gate pbm_err_p->pbm_bridge_type = PCI_BRIDGE_TYPE(pci_p->pci_common_p);
19130Sstevel@tonic-gate pbm_err_p->pbm_pci.pci_cfg_stat =
19140Sstevel@tonic-gate pbm_p->pbm_config_header->ch_status_reg;
19150Sstevel@tonic-gate pbm_err_p->pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
19160Sstevel@tonic-gate pbm_err_p->pbm_pci.pci_cfg_comm =
19170Sstevel@tonic-gate pbm_p->pbm_config_header->ch_command_reg;
19180Sstevel@tonic-gate pbm_err_p->pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
19190Sstevel@tonic-gate pbm_err_p->pbm_afar = *pbm_p->pbm_async_flt_addr_reg;
19200Sstevel@tonic-gate pbm_err_p->pbm_pci.pci_pa = *pbm_p->pbm_async_flt_addr_reg;
19210Sstevel@tonic-gate }
19220Sstevel@tonic-gate
19230Sstevel@tonic-gate void
pbm_clear_error(pbm_t * pbm_p)19240Sstevel@tonic-gate pbm_clear_error(pbm_t *pbm_p)
19250Sstevel@tonic-gate {
19260Sstevel@tonic-gate uint64_t pbm_afsr, pbm_ctl_stat;
19270Sstevel@tonic-gate
19280Sstevel@tonic-gate /*
19290Sstevel@tonic-gate * for poke() support - called from POKE_FLUSH. Spin waiting
19300Sstevel@tonic-gate * for MA, TA or SERR to be cleared by a pbm_error_intr().
19310Sstevel@tonic-gate * We have to wait for SERR too in case the device is beyond
19320Sstevel@tonic-gate * a pci-pci bridge.
19330Sstevel@tonic-gate */
19340Sstevel@tonic-gate pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
19350Sstevel@tonic-gate pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
19360Sstevel@tonic-gate while (((pbm_afsr >> PSYCHO_PCI_AFSR_PE_SHIFT) &
19370Sstevel@tonic-gate (PSYCHO_PCI_AFSR_E_MA | PSYCHO_PCI_AFSR_E_TA)) ||
19380Sstevel@tonic-gate (pbm_ctl_stat & COMMON_PCI_CTRL_SERR)) {
19390Sstevel@tonic-gate pbm_ctl_stat = *pbm_p->pbm_ctrl_reg;
19400Sstevel@tonic-gate pbm_afsr = *pbm_p->pbm_async_flt_status_reg;
19410Sstevel@tonic-gate }
19420Sstevel@tonic-gate }
19430Sstevel@tonic-gate
19440Sstevel@tonic-gate /*ARGSUSED*/
19450Sstevel@tonic-gate void
pci_format_addr(dev_info_t * dip,uint64_t * afar,uint64_t afsr)19460Sstevel@tonic-gate pci_format_addr(dev_info_t *dip, uint64_t *afar, uint64_t afsr)
19470Sstevel@tonic-gate {
19480Sstevel@tonic-gate /*
19490Sstevel@tonic-gate * For Psycho the full address is stored in hardware. So
19500Sstevel@tonic-gate * there is no need to format it.
19510Sstevel@tonic-gate */
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate /*ARGSUSED*/
19550Sstevel@tonic-gate int
pci_bus_quiesce(pci_t * pci_p,dev_info_t * dip,void * result)19560Sstevel@tonic-gate pci_bus_quiesce(pci_t *pci_p, dev_info_t *dip, void *result)
19570Sstevel@tonic-gate {
19580Sstevel@tonic-gate return (DDI_FAILURE);
19590Sstevel@tonic-gate }
19600Sstevel@tonic-gate
19610Sstevel@tonic-gate /*ARGSUSED*/
19620Sstevel@tonic-gate int
pci_bus_unquiesce(pci_t * pci_p,dev_info_t * dip,void * result)19630Sstevel@tonic-gate pci_bus_unquiesce(pci_t *pci_p, dev_info_t *dip, void *result)
19640Sstevel@tonic-gate {
19650Sstevel@tonic-gate return (DDI_FAILURE);
19660Sstevel@tonic-gate }
19670Sstevel@tonic-gate
19682251Selowe int
pci_reloc_getkey(void)19692251Selowe pci_reloc_getkey(void)
19702251Selowe {
19712251Selowe return (0x100);
19722251Selowe }
19732251Selowe
19740Sstevel@tonic-gate void
pci_vmem_free(iommu_t * iommu_p,ddi_dma_impl_t * mp,void * dvma_addr,size_t npages)19750Sstevel@tonic-gate pci_vmem_free(iommu_t *iommu_p, ddi_dma_impl_t *mp, void *dvma_addr,
19760Sstevel@tonic-gate size_t npages)
19770Sstevel@tonic-gate {
19780Sstevel@tonic-gate pci_vmem_do_free(iommu_p, dvma_addr, npages,
19790Sstevel@tonic-gate (mp->dmai_flags & DMAI_FLAGS_VMEMCACHE));
19800Sstevel@tonic-gate }
19810Sstevel@tonic-gate
19820Sstevel@tonic-gate
19830Sstevel@tonic-gate /*
19840Sstevel@tonic-gate * NOTE: This call is only used by legacy systems (eg. E250 and E450) that
19850Sstevel@tonic-gate * require unregistering the pci driver's thermal intrerrupt handler before
19860Sstevel@tonic-gate * they can register their own.
19870Sstevel@tonic-gate */
19880Sstevel@tonic-gate void
pci_thermal_rem_intr(dev_info_t * rdip,uint_t inum)19890Sstevel@tonic-gate pci_thermal_rem_intr(dev_info_t *rdip, uint_t inum)
19900Sstevel@tonic-gate {
19910Sstevel@tonic-gate pci_t *pci_p;
19920Sstevel@tonic-gate dev_info_t *pdip;
19930Sstevel@tonic-gate uint32_t dev_mondo, pci_mondo;
19940Sstevel@tonic-gate int instance;
19950Sstevel@tonic-gate
19960Sstevel@tonic-gate for (pdip = ddi_get_parent(rdip); pdip; pdip = ddi_get_parent(pdip)) {
19970Sstevel@tonic-gate if (strcmp(ddi_driver_name(pdip), "pcipsy") == 0)
19980Sstevel@tonic-gate break;
19990Sstevel@tonic-gate }
20000Sstevel@tonic-gate
20010Sstevel@tonic-gate if (!pdip) {
20020Sstevel@tonic-gate cmn_err(CE_WARN, "pci_thermal_rem_intr() no pcipsy parent\n");
20030Sstevel@tonic-gate return;
20040Sstevel@tonic-gate }
20050Sstevel@tonic-gate
20060Sstevel@tonic-gate instance = ddi_get_instance(pdip);
20070Sstevel@tonic-gate pci_p = get_pci_soft_state(instance);
20080Sstevel@tonic-gate
20090Sstevel@tonic-gate /* Calculate the requesting device's mondo */
20100Sstevel@tonic-gate dev_mondo = pci_xlate_intr(pci_p->pci_dip, rdip, pci_p->pci_ib_p,
2011693Sgovinda IB_MONDO_TO_INO(i_ddi_get_inum(rdip, inum)));
20120Sstevel@tonic-gate
20130Sstevel@tonic-gate /* get pci's thermal mondo */
20140Sstevel@tonic-gate pci_mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) |
20150Sstevel@tonic-gate pci_p->pci_inos[CBNINTR_THERMAL]);
20160Sstevel@tonic-gate pci_mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, pci_mondo);
20170Sstevel@tonic-gate
20180Sstevel@tonic-gate if (pci_mondo == dev_mondo) {
20190Sstevel@tonic-gate DEBUG2(DBG_ATTACH, rdip, "pci_thermal_rem_intr unregistered "
20200Sstevel@tonic-gate "for dip=%s%d:", ddi_driver_name(rdip),
20210Sstevel@tonic-gate ddi_get_instance(rdip));
20222973Sgovinda VERIFY(rem_ivintr(pci_mondo, pci_pil[CBNINTR_THERMAL]) == 0);
20230Sstevel@tonic-gate }
20240Sstevel@tonic-gate }
20252050Ssuha
20262050Ssuha /*
20272050Ssuha * pci_iommu_bypass_end_configure
20282050Ssuha *
20292050Ssuha * Support for 40-bit bus width to UPA in DVMA and iommu bypass transfers:
20302050Ssuha */
20312050Ssuha
20322050Ssuha dma_bypass_addr_t
pci_iommu_bypass_end_configure(void)20332050Ssuha pci_iommu_bypass_end_configure(void)
20342050Ssuha {
20352050Ssuha
20362050Ssuha return ((dma_bypass_addr_t)UPA_IOMMU_BYPASS_END);
20372050Ssuha }
2038