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 /* 221817Sarutz * Copyright 2006 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/ivintr.h> 420Sstevel@tonic-gate #include <sys/systm.h> 430Sstevel@tonic-gate #include <sys/intreg.h> /* UPAID_TO_IGN() */ 440Sstevel@tonic-gate #include <sys/intr.h> 450Sstevel@tonic-gate #include <sys/sunddi.h> 460Sstevel@tonic-gate #include <sys/sunndi.h> 470Sstevel@tonic-gate #include <sys/machsystm.h> 480Sstevel@tonic-gate #include <sys/fm/util.h> 490Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 500Sstevel@tonic-gate #include <sys/iommutsb.h> 510Sstevel@tonic-gate #include <sys/spl.h> 520Sstevel@tonic-gate #include <sys/fm/util.h> 530Sstevel@tonic-gate #include <sys/fm/protocol.h> 540Sstevel@tonic-gate #include <sys/fm/io/pci.h> 550Sstevel@tonic-gate #include <sys/fm/io/sun4upci.h> 560Sstevel@tonic-gate #include <sys/pci/pci_obj.h> 570Sstevel@tonic-gate #include <sys/pci/pcipsy.h> 580Sstevel@tonic-gate 590Sstevel@tonic-gate #ifdef _STARFIRE 600Sstevel@tonic-gate #include <sys/starfire.h> 610Sstevel@tonic-gate #endif /* _STARFIRE */ 620Sstevel@tonic-gate 630Sstevel@tonic-gate static uint32_t pci_identity_init(pci_t *pci_p); 640Sstevel@tonic-gate static int pci_intr_setup(pci_t *pci_p); 650Sstevel@tonic-gate static void pci_pbm_errstate_get(pci_t *pci_p, pbm_errstate_t *pbm_err_p); 660Sstevel@tonic-gate 670Sstevel@tonic-gate static pci_ksinfo_t *pci_name_kstat; 680Sstevel@tonic-gate 690Sstevel@tonic-gate /*LINTLIBRARY*/ 700Sstevel@tonic-gate /* called by pci_attach() DDI_ATTACH to initialize pci objects */ 710Sstevel@tonic-gate int 720Sstevel@tonic-gate pci_obj_setup(pci_t *pci_p) 730Sstevel@tonic-gate { 740Sstevel@tonic-gate pci_common_t *cmn_p; 750Sstevel@tonic-gate int ret; 760Sstevel@tonic-gate 770Sstevel@tonic-gate mutex_enter(&pci_global_mutex); 780Sstevel@tonic-gate cmn_p = get_pci_common_soft_state(pci_p->pci_id); 790Sstevel@tonic-gate if (cmn_p == NULL) { 800Sstevel@tonic-gate uint_t id = pci_p->pci_id; 810Sstevel@tonic-gate if (alloc_pci_common_soft_state(id) != DDI_SUCCESS) { 820Sstevel@tonic-gate mutex_exit(&pci_global_mutex); 830Sstevel@tonic-gate return (DDI_FAILURE); 840Sstevel@tonic-gate } 850Sstevel@tonic-gate cmn_p = get_pci_common_soft_state(id); 860Sstevel@tonic-gate cmn_p->pci_common_id = id; 870Sstevel@tonic-gate } 880Sstevel@tonic-gate 890Sstevel@tonic-gate ASSERT((pci_p->pci_side == 0) || (pci_p->pci_side == 1)); 900Sstevel@tonic-gate if (cmn_p->pci_p[pci_p->pci_side]) { 910Sstevel@tonic-gate /* second side attach */ 920Sstevel@tonic-gate pci_p->pci_side = PCI_OTHER_SIDE(pci_p->pci_side); 930Sstevel@tonic-gate ASSERT(cmn_p->pci_p[pci_p->pci_side] == NULL); 940Sstevel@tonic-gate } 950Sstevel@tonic-gate 960Sstevel@tonic-gate cmn_p->pci_p[pci_p->pci_side] = pci_p; 970Sstevel@tonic-gate pci_p->pci_common_p = cmn_p; 980Sstevel@tonic-gate 990Sstevel@tonic-gate if (cmn_p->pci_common_refcnt == 0) { 1000Sstevel@tonic-gate /* Perform allocation first to avoid delicate unwinding. */ 1010Sstevel@tonic-gate if (pci_alloc_tsb(pci_p) != DDI_SUCCESS) { 1020Sstevel@tonic-gate cmn_p->pci_p[pci_p->pci_side] = NULL; 1030Sstevel@tonic-gate pci_p->pci_common_p = NULL; 1040Sstevel@tonic-gate free_pci_common_soft_state(cmn_p->pci_common_id); 1050Sstevel@tonic-gate mutex_exit(&pci_global_mutex); 1060Sstevel@tonic-gate return (DDI_FAILURE); 1070Sstevel@tonic-gate } 1080Sstevel@tonic-gate cmn_p->pci_common_tsb_cookie = pci_p->pci_tsb_cookie; 1090Sstevel@tonic-gate cmn_p->pci_chip_id = pci_identity_init(pci_p); 1100Sstevel@tonic-gate 1110Sstevel@tonic-gate ib_create(pci_p); 1120Sstevel@tonic-gate cmn_p->pci_common_ib_p = pci_p->pci_ib_p; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate cb_create(pci_p); 1150Sstevel@tonic-gate cmn_p->pci_common_cb_p = pci_p->pci_cb_p; 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate iommu_create(pci_p); 1180Sstevel@tonic-gate cmn_p->pci_common_iommu_p = pci_p->pci_iommu_p; 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate ecc_create(pci_p); 1210Sstevel@tonic-gate cmn_p->pci_common_ecc_p = pci_p->pci_ecc_p; 1220Sstevel@tonic-gate } else { 1230Sstevel@tonic-gate ASSERT(cmn_p->pci_common_refcnt == 1); 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate pci_p->pci_tsb_cookie = cmn_p->pci_common_tsb_cookie; 1260Sstevel@tonic-gate pci_p->pci_ib_p = cmn_p->pci_common_ib_p; 1270Sstevel@tonic-gate pci_p->pci_cb_p = cmn_p->pci_common_cb_p; 1280Sstevel@tonic-gate pci_p->pci_iommu_p = cmn_p->pci_common_iommu_p; 1290Sstevel@tonic-gate pci_p->pci_ecc_p = cmn_p->pci_common_ecc_p; 1300Sstevel@tonic-gate } 1310Sstevel@tonic-gate 1320Sstevel@tonic-gate pbm_create(pci_p); 1330Sstevel@tonic-gate sc_create(pci_p); 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate pci_fm_create(pci_p); 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate if ((ret = pci_intr_setup(pci_p)) != DDI_SUCCESS) 1380Sstevel@tonic-gate goto done; 1390Sstevel@tonic-gate if (CHIP_TYPE(pci_p) == PCI_CHIP_PSYCHO) 1400Sstevel@tonic-gate pci_kstat_create(pci_p); 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate cmn_p->pci_common_attachcnt++; 1430Sstevel@tonic-gate cmn_p->pci_common_refcnt++; 1440Sstevel@tonic-gate done: 1450Sstevel@tonic-gate mutex_exit(&pci_global_mutex); 1460Sstevel@tonic-gate if (ret != DDI_SUCCESS) 1470Sstevel@tonic-gate cmn_err(CE_NOTE, "Interrupt register failure, returning 0x%x\n", 1480Sstevel@tonic-gate ret); 1490Sstevel@tonic-gate return (ret); 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate /* called by pci_detach() DDI_DETACH to destroy pci objects */ 1530Sstevel@tonic-gate void 1540Sstevel@tonic-gate pci_obj_destroy(pci_t *pci_p) 1550Sstevel@tonic-gate { 1560Sstevel@tonic-gate pci_common_t *cmn_p; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate mutex_enter(&pci_global_mutex); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate cmn_p = pci_p->pci_common_p; 1610Sstevel@tonic-gate cmn_p->pci_common_refcnt--; 1620Sstevel@tonic-gate cmn_p->pci_common_attachcnt--; 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate pci_kstat_destroy(pci_p); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate sc_destroy(pci_p); 1670Sstevel@tonic-gate pbm_destroy(pci_p); 1680Sstevel@tonic-gate pci_fm_destroy(pci_p); 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate if (cmn_p->pci_common_refcnt != 0) { 1710Sstevel@tonic-gate cmn_p->pci_p[pci_p->pci_side] = NULL; 1720Sstevel@tonic-gate mutex_exit(&pci_global_mutex); 1730Sstevel@tonic-gate return; 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate ecc_destroy(pci_p); 1770Sstevel@tonic-gate iommu_destroy(pci_p); 1780Sstevel@tonic-gate cb_destroy(pci_p); 1790Sstevel@tonic-gate ib_destroy(pci_p); 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate free_pci_common_soft_state(cmn_p->pci_common_id); 1820Sstevel@tonic-gate pci_intr_teardown(pci_p); 1830Sstevel@tonic-gate mutex_exit(&pci_global_mutex); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* called by pci_attach() DDI_RESUME to (re)initialize pci objects */ 1870Sstevel@tonic-gate void 1880Sstevel@tonic-gate pci_obj_resume(pci_t *pci_p) 1890Sstevel@tonic-gate { 1900Sstevel@tonic-gate pci_common_t *cmn_p = pci_p->pci_common_p; 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate mutex_enter(&pci_global_mutex); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate if (cmn_p->pci_common_attachcnt == 0) { 1950Sstevel@tonic-gate ib_configure(pci_p->pci_ib_p); 1960Sstevel@tonic-gate iommu_configure(pci_p->pci_iommu_p); 1970Sstevel@tonic-gate ecc_configure(pci_p); 1980Sstevel@tonic-gate ib_resume(pci_p->pci_ib_p); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate pbm_configure(pci_p->pci_pbm_p); 2020Sstevel@tonic-gate sc_configure(pci_p->pci_sc_p); 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate if (cmn_p->pci_common_attachcnt == 0) 2050Sstevel@tonic-gate cb_resume(pci_p->pci_cb_p); 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate pbm_resume(pci_p->pci_pbm_p); 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate cmn_p->pci_common_attachcnt++; 2100Sstevel@tonic-gate mutex_exit(&pci_global_mutex); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate /* called by pci_detach() DDI_SUSPEND to suspend pci objects */ 2140Sstevel@tonic-gate void 2150Sstevel@tonic-gate pci_obj_suspend(pci_t *pci_p) 2160Sstevel@tonic-gate { 2170Sstevel@tonic-gate mutex_enter(&pci_global_mutex); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate pbm_suspend(pci_p->pci_pbm_p); 2200Sstevel@tonic-gate if (!--pci_p->pci_common_p->pci_common_attachcnt) { 2210Sstevel@tonic-gate ib_suspend(pci_p->pci_ib_p); 2220Sstevel@tonic-gate cb_suspend(pci_p->pci_cb_p); 2230Sstevel@tonic-gate } 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate mutex_exit(&pci_global_mutex); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate static uint32_t javelin_prom_fix[] = {0xfff800, 0, 0, 0x3f}; 2290Sstevel@tonic-gate static int 2300Sstevel@tonic-gate pci_intr_setup(pci_t *pci_p) 2310Sstevel@tonic-gate { 2320Sstevel@tonic-gate extern char *platform; 2330Sstevel@tonic-gate dev_info_t *dip = pci_p->pci_dip; 2340Sstevel@tonic-gate pbm_t *pbm_p = pci_p->pci_pbm_p; 2350Sstevel@tonic-gate cb_t *cb_p = pci_p->pci_cb_p; 2360Sstevel@tonic-gate int i, no_of_intrs; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* 2390Sstevel@tonic-gate * This is a hack to fix a broken imap entry in the javelin PROM. 2400Sstevel@tonic-gate * see bugid 4226603 2410Sstevel@tonic-gate */ 2420Sstevel@tonic-gate if (strcmp((const char *)&platform, "SUNW,Ultra-250") == 0) 2430Sstevel@tonic-gate (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 2440Sstevel@tonic-gate "interrupt-map-mask", (caddr_t)javelin_prom_fix, 2450Sstevel@tonic-gate sizeof (javelin_prom_fix)); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate /* 2480Sstevel@tonic-gate * Get the interrupts property. 2490Sstevel@tonic-gate */ 250506Scth if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 2510Sstevel@tonic-gate "interrupts", (caddr_t)&pci_p->pci_inos, 2520Sstevel@tonic-gate &pci_p->pci_inos_len) != DDI_SUCCESS) 2530Sstevel@tonic-gate cmn_err(CE_PANIC, "%s%d: no interrupts property\n", 2540Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip)); 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* 2570Sstevel@tonic-gate * figure out number of interrupts in the "interrupts" property 2580Sstevel@tonic-gate * and convert them all into ino. 2590Sstevel@tonic-gate */ 2600Sstevel@tonic-gate i = ddi_getprop(DDI_DEV_T_ANY, dip, 0, "#interrupt-cells", 1); 2610Sstevel@tonic-gate i = CELLS_1275_TO_BYTES(i); 2620Sstevel@tonic-gate no_of_intrs = pci_p->pci_inos_len / i; 2630Sstevel@tonic-gate for (i = 0; i < no_of_intrs; i++) 2640Sstevel@tonic-gate pci_p->pci_inos[i] = IB_MONDO_TO_INO(pci_p->pci_inos[i]); 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate if (pci_p->pci_common_p->pci_common_refcnt == 0) { 2670Sstevel@tonic-gate cb_p->cb_no_of_inos = no_of_intrs; 2680Sstevel@tonic-gate if (i = cb_register_intr(pci_p)) 2690Sstevel@tonic-gate goto teardown; 2700Sstevel@tonic-gate if (i = ecc_register_intr(pci_p)) 2710Sstevel@tonic-gate goto teardown; 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate intr_dist_add(cb_intr_dist, cb_p); 2740Sstevel@tonic-gate cb_enable_intr(pci_p); 2750Sstevel@tonic-gate ecc_enable_intr(pci_p); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate if (i = pbm_register_intr(pbm_p)) { 2790Sstevel@tonic-gate if (pci_p->pci_common_p->pci_common_refcnt == 0) 2800Sstevel@tonic-gate intr_dist_rem(cb_intr_dist, cb_p); 2810Sstevel@tonic-gate goto teardown; 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate intr_dist_add(pbm_intr_dist, pbm_p); 2840Sstevel@tonic-gate ib_intr_enable(pci_p, pci_p->pci_inos[CBNINTR_PBM]); 2850Sstevel@tonic-gate 2860Sstevel@tonic-gate if (pci_p->pci_common_p->pci_common_refcnt == 0) 2870Sstevel@tonic-gate intr_dist_add_weighted(ib_intr_dist_all, pci_p->pci_ib_p); 2880Sstevel@tonic-gate return (DDI_SUCCESS); 2890Sstevel@tonic-gate teardown: 2900Sstevel@tonic-gate pci_intr_teardown(pci_p); 2910Sstevel@tonic-gate return (i); 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate /* 2950Sstevel@tonic-gate * pci_fix_ranges - fixes the config space entry of the "ranges" 2960Sstevel@tonic-gate * property on psycho+ platforms 2970Sstevel@tonic-gate */ 2980Sstevel@tonic-gate void 2990Sstevel@tonic-gate pci_fix_ranges(pci_ranges_t *rng_p, int rng_entries) 3000Sstevel@tonic-gate { 3010Sstevel@tonic-gate int i; 3020Sstevel@tonic-gate for (i = 0; i < rng_entries; i++, rng_p++) 3030Sstevel@tonic-gate if ((rng_p->child_high & PCI_REG_ADDR_M) == PCI_ADDR_CONFIG) 3040Sstevel@tonic-gate rng_p->parent_low |= rng_p->child_high; 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate /* 3080Sstevel@tonic-gate * map_pci_registers 3090Sstevel@tonic-gate * 3100Sstevel@tonic-gate * This function is called from the attach routine to map the registers 3110Sstevel@tonic-gate * accessed by this driver. 3120Sstevel@tonic-gate * 3130Sstevel@tonic-gate * used by: pci_attach() 3140Sstevel@tonic-gate * 3150Sstevel@tonic-gate * return value: DDI_FAILURE on failure 3160Sstevel@tonic-gate */ 3170Sstevel@tonic-gate int 3180Sstevel@tonic-gate map_pci_registers(pci_t *pci_p, dev_info_t *dip) 3190Sstevel@tonic-gate { 3200Sstevel@tonic-gate ddi_device_acc_attr_t attr; 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 3230Sstevel@tonic-gate attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 3260Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 0, &pci_p->pci_address[0], 0, 0, 3270Sstevel@tonic-gate &attr, &pci_p->pci_ac[0]) != DDI_SUCCESS) { 3280Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unable to map reg entry 0\n", 3290Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip)); 3300Sstevel@tonic-gate return (DDI_FAILURE); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate /* 3330Sstevel@tonic-gate * if we don't have streaming buffer, then we don't have 3340Sstevel@tonic-gate * pci_address[2]. 3350Sstevel@tonic-gate */ 3360Sstevel@tonic-gate if (pci_stream_buf_exists && 3370Sstevel@tonic-gate ddi_regs_map_setup(dip, 2, &pci_p->pci_address[2], 0, 0, 3380Sstevel@tonic-gate &attr, &pci_p->pci_ac[2]) != DDI_SUCCESS) { 3390Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unable to map reg entry 2\n", 3400Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip)); 3410Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[0]); 3420Sstevel@tonic-gate return (DDI_FAILURE); 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * The second register set contains the bridge's configuration 3470Sstevel@tonic-gate * header. This header is at the very beginning of the bridge's 3480Sstevel@tonic-gate * configuration space. This space has litte-endian byte order. 3490Sstevel@tonic-gate */ 3500Sstevel@tonic-gate attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 3510Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 1, &pci_p->pci_address[1], 0, 3520Sstevel@tonic-gate PCI_CONF_HDR_SIZE, &attr, &pci_p->pci_ac[1]) != DDI_SUCCESS) { 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: unable to map reg entry 1\n", 3550Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip)); 3560Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[0]); 3570Sstevel@tonic-gate if (pci_stream_buf_exists) 3580Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[2]); 3590Sstevel@tonic-gate return (DDI_FAILURE); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate DEBUG3(DBG_ATTACH, dip, "address (%p,%p,%p)\n", 3620Sstevel@tonic-gate pci_p->pci_address[0], pci_p->pci_address[1], 3630Sstevel@tonic-gate pci_p->pci_address[2]); 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate return (DDI_SUCCESS); 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate /* 3690Sstevel@tonic-gate * unmap_pci_registers: 3700Sstevel@tonic-gate * 3710Sstevel@tonic-gate * This routine unmap the registers mapped by map_pci_registers. 3720Sstevel@tonic-gate * 3730Sstevel@tonic-gate * used by: pci_detach() 3740Sstevel@tonic-gate * 3750Sstevel@tonic-gate * return value: none 3760Sstevel@tonic-gate */ 3770Sstevel@tonic-gate void 3780Sstevel@tonic-gate unmap_pci_registers(pci_t *pci_p) 3790Sstevel@tonic-gate { 3800Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[0]); 3810Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[1]); 3820Sstevel@tonic-gate if (pci_stream_buf_exists) 3830Sstevel@tonic-gate ddi_regs_map_free(&pci_p->pci_ac[2]); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate /* 3870Sstevel@tonic-gate * These convenience wrappers relies on map_pci_registers() to setup 3880Sstevel@tonic-gate * pci_address[0-2] correctly at first. 3890Sstevel@tonic-gate */ 3900Sstevel@tonic-gate /* The psycho+ reg base is at 1fe.0000.0000 */ 3910Sstevel@tonic-gate static uintptr_t 3920Sstevel@tonic-gate get_reg_base(pci_t *pci_p) 3930Sstevel@tonic-gate { 3940Sstevel@tonic-gate return ((uintptr_t)pci_p->pci_address[pci_stream_buf_exists ? 2 : 0]); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate /* The psycho+ config reg base is always the 2nd reg entry */ 3980Sstevel@tonic-gate static uintptr_t 3990Sstevel@tonic-gate get_config_reg_base(pci_t *pci_p) 4000Sstevel@tonic-gate { 4010Sstevel@tonic-gate return ((uintptr_t)(pci_p->pci_address[1])); 4020Sstevel@tonic-gate } 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate uint64_t 4050Sstevel@tonic-gate ib_get_map_reg(ib_mondo_t mondo, uint32_t cpu_id) 4060Sstevel@tonic-gate { 4070Sstevel@tonic-gate return ((mondo) | (cpu_id << COMMON_INTR_MAP_REG_TID_SHIFT) | 4080Sstevel@tonic-gate COMMON_INTR_MAP_REG_VALID); 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate uint32_t 4130Sstevel@tonic-gate ib_map_reg_get_cpu(volatile uint64_t reg) 4140Sstevel@tonic-gate { 4150Sstevel@tonic-gate return ((reg & COMMON_INTR_MAP_REG_TID) >> 4160Sstevel@tonic-gate COMMON_INTR_MAP_REG_TID_SHIFT); 4170Sstevel@tonic-gate } 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate uint64_t * 4200Sstevel@tonic-gate ib_intr_map_reg_addr(ib_t *ib_p, ib_ino_t ino) 4210Sstevel@tonic-gate { 4220Sstevel@tonic-gate uint64_t *addr; 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate if (ino & 0x20) 4250Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_obio_intr_map_regs + 4260Sstevel@tonic-gate (((uint_t)ino & 0x1f) << 3)); 4270Sstevel@tonic-gate else 4280Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_slot_intr_map_regs + 4290Sstevel@tonic-gate (((uint_t)ino & 0x3c) << 1)); 4300Sstevel@tonic-gate return (addr); 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate uint64_t * 4340Sstevel@tonic-gate ib_clear_intr_reg_addr(ib_t *ib_p, ib_ino_t ino) 4350Sstevel@tonic-gate { 4360Sstevel@tonic-gate uint64_t *addr; 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate if (ino & 0x20) 4390Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_obio_clear_intr_regs + 4400Sstevel@tonic-gate (((uint_t)ino & 0x1f) << 3)); 4410Sstevel@tonic-gate else 4420Sstevel@tonic-gate addr = (uint64_t *)(ib_p->ib_slot_clear_intr_regs + 4430Sstevel@tonic-gate (((uint_t)ino & 0x1f) << 3)); 4440Sstevel@tonic-gate return (addr); 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate /* 4480Sstevel@tonic-gate * psycho have one mapping register per slot 4490Sstevel@tonic-gate */ 4500Sstevel@tonic-gate void 4510Sstevel@tonic-gate ib_ino_map_reg_share(ib_t *ib_p, ib_ino_t ino, ib_ino_info_t *ino_p) 4520Sstevel@tonic-gate { 4530Sstevel@tonic-gate if (!IB_IS_OBIO_INO(ino)) { 4540Sstevel@tonic-gate ASSERT(ino_p->ino_slot_no < 8); 4550Sstevel@tonic-gate ib_p->ib_map_reg_counters[ino_p->ino_slot_no]++; 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate } 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate /* 4600Sstevel@tonic-gate * return true if the ino shares mapping register with other interrupts 4610Sstevel@tonic-gate * of the same slot, or is still shared by other On-board devices. 4620Sstevel@tonic-gate */ 4630Sstevel@tonic-gate int 4640Sstevel@tonic-gate ib_ino_map_reg_unshare(ib_t *ib_p, ib_ino_t ino, ib_ino_info_t *ino_p) 4650Sstevel@tonic-gate { 4660Sstevel@tonic-gate ASSERT(IB_IS_OBIO_INO(ino) || ino_p->ino_slot_no < 8); 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate if (IB_IS_OBIO_INO(ino)) 4690Sstevel@tonic-gate return (ino_p->ino_ih_size); 4700Sstevel@tonic-gate else 4710Sstevel@tonic-gate return (--ib_p->ib_map_reg_counters[ino_p->ino_slot_no]); 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /*ARGSUSED*/ 4750Sstevel@tonic-gate void 4760Sstevel@tonic-gate pci_pbm_intr_dist(pbm_t *pbm_p) 4770Sstevel@tonic-gate { 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate uintptr_t 4810Sstevel@tonic-gate pci_ib_setup(ib_t *ib_p) 4820Sstevel@tonic-gate { 4830Sstevel@tonic-gate pci_t *pci_p = ib_p->ib_pci_p; 4840Sstevel@tonic-gate uintptr_t a = get_reg_base(pci_p); 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate ib_p->ib_ign = PCI_ID_TO_IGN(pci_p->pci_id); 4870Sstevel@tonic-gate ib_p->ib_max_ino = PSYCHO_MAX_INO; 4880Sstevel@tonic-gate ib_p->ib_slot_intr_map_regs = a + PSYCHO_IB_SLOT_INTR_MAP_REG_OFFSET; 4890Sstevel@tonic-gate ib_p->ib_obio_intr_map_regs = a + PSYCHO_IB_OBIO_INTR_MAP_REG_OFFSET; 4900Sstevel@tonic-gate ib_p->ib_obio_clear_intr_regs = 4910Sstevel@tonic-gate a + PSYCHO_IB_OBIO_CLEAR_INTR_REG_OFFSET; 4920Sstevel@tonic-gate return (a); 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate uint32_t 4960Sstevel@tonic-gate pci_xlate_intr(dev_info_t *dip, dev_info_t *rdip, ib_t *ib_p, uint32_t intr) 4970Sstevel@tonic-gate { 4980Sstevel@tonic-gate int32_t len; 4990Sstevel@tonic-gate dev_info_t *cdip; 5000Sstevel@tonic-gate pci_regspec_t *pci_rp; 5010Sstevel@tonic-gate uint32_t bus, dev, phys_hi; 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate if ((intr > PCI_INTD) || (intr < PCI_INTA)) 5040Sstevel@tonic-gate goto done; 5050Sstevel@tonic-gate if (ddi_prop_exists(DDI_DEV_T_ANY, rdip, NULL, "interrupt-map")) 5060Sstevel@tonic-gate goto done; 5070Sstevel@tonic-gate /* 5080Sstevel@tonic-gate * Hack for pre 1275 imap machines e.g. quark & tazmo 5090Sstevel@tonic-gate * We need to turn any PCI interrupts into ino interrupts. machines 5100Sstevel@tonic-gate * supporting imap will have this done in the map. 5110Sstevel@tonic-gate */ 5120Sstevel@tonic-gate cdip = get_my_childs_dip(dip, rdip); 5130Sstevel@tonic-gate if (ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, "reg", 5140Sstevel@tonic-gate (caddr_t)&pci_rp, &len) != DDI_SUCCESS) 5150Sstevel@tonic-gate return (0); 5160Sstevel@tonic-gate phys_hi = pci_rp->pci_phys_hi; 5170Sstevel@tonic-gate kmem_free(pci_rp, len); 5180Sstevel@tonic-gate 5190Sstevel@tonic-gate bus = PCI_REG_BUS_G(phys_hi); 5200Sstevel@tonic-gate dev = PCI_REG_DEV_G(phys_hi); 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate /* 5230Sstevel@tonic-gate * The ino for a given device id is derived as 0BSSNN where 5240Sstevel@tonic-gate * 5250Sstevel@tonic-gate * B = 0 for bus A, 1 for bus B 5260Sstevel@tonic-gate * SS = dev - 1 for bus A, dev - 2 for bus B 5270Sstevel@tonic-gate * NN = 00 for INTA#, 01 for INTB#, 10 for INTC#, 11 for INTD# 5280Sstevel@tonic-gate * 5290Sstevel@tonic-gate * if pci bus number > 0x80, then devices are located on the A side(66) 5300Sstevel@tonic-gate */ 5310Sstevel@tonic-gate DEBUG3(DBG_IB, dip, "pci_xlate_intr: bus=%x, dev=%x, intr=%x\n", 5320Sstevel@tonic-gate bus, dev, intr); 5330Sstevel@tonic-gate intr--; 5340Sstevel@tonic-gate intr |= (bus & 0x80) ? ((dev - 1) << 2) : (0x10 | ((dev - 2) << 2)); 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate DEBUG1(DBG_IB, dip, "pci_xlate_intr: done ino=%x\n", intr); 5370Sstevel@tonic-gate done: 5380Sstevel@tonic-gate return (IB_INO_TO_MONDO(ib_p, intr)); 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate /* 5420Sstevel@tonic-gate * Return the cpuid to to be used for an ino. Psycho has special slot-cpu 5430Sstevel@tonic-gate * constraints on cpu assignment: 5440Sstevel@tonic-gate * 5450Sstevel@tonic-gate * On multi-function pci cards, functions have separate devinfo nodes and 5460Sstevel@tonic-gate * interrupts. Some pci support hardware, such as the psycho/pcipsy chip, 5470Sstevel@tonic-gate * control interrupt-to-cpu binding on a per pci-slot basis instead of per 5480Sstevel@tonic-gate * function. For hardware like this, if an interrupt for one function has 5490Sstevel@tonic-gate * already been directed to a particular cpu, we can't choose a different 5500Sstevel@tonic-gate * cpu for another function implemented in the same pci-slot - if we did 5510Sstevel@tonic-gate * we would be redirecting the first function too (which causes problems 5520Sstevel@tonic-gate * for consistent interrupt distribution). 5530Sstevel@tonic-gate * 5540Sstevel@tonic-gate * This function determines if there is already an established slot-oriented 5550Sstevel@tonic-gate * interrupt-to-cpu binding established, if there is then it returns that 5560Sstevel@tonic-gate * cpu. Otherwise a new cpu is selected by intr_dist_cpuid(). 5570Sstevel@tonic-gate * 5580Sstevel@tonic-gate * The devinfo node we are trying to associate a cpu with is 5590Sstevel@tonic-gate * ino_p->ino_ih_head->ih_dip. 5600Sstevel@tonic-gate */ 5610Sstevel@tonic-gate uint32_t 5620Sstevel@tonic-gate pci_intr_dist_cpuid(ib_t *ib_p, ib_ino_info_t *ino_p) 5630Sstevel@tonic-gate { 5640Sstevel@tonic-gate dev_info_t *rdip = ino_p->ino_ih_head->ih_dip; 5650Sstevel@tonic-gate dev_info_t *prdip = ddi_get_parent(rdip); 5660Sstevel@tonic-gate ib_ino_info_t *sino_p; 5670Sstevel@tonic-gate dev_info_t *sdip; 5680Sstevel@tonic-gate dev_info_t *psdip; 5690Sstevel@tonic-gate char *buf1 = NULL, *buf2 = NULL; 5700Sstevel@tonic-gate char *s1, *s2, *s3; 5710Sstevel@tonic-gate int l2; 5720Sstevel@tonic-gate int cpu_id; 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate /* must be psycho driver parent (not ebus) */ 5750Sstevel@tonic-gate if (strcmp(ddi_driver_name(prdip), "pcipsy") != 0) 5760Sstevel@tonic-gate goto newcpu; 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate /* 5790Sstevel@tonic-gate * From PCI 1275 binding: 2.2.1.3 Unit Address representation: 5800Sstevel@tonic-gate * Since the "unit-number" is the address that appears in on Open 5810Sstevel@tonic-gate * Firmware 'device path', it follows that only the DD and DD,FF 5820Sstevel@tonic-gate * forms of the text representation can appear in a 'device path'. 5830Sstevel@tonic-gate * 5840Sstevel@tonic-gate * The rdip unit address is of the form "DD[,FF]". Define two 5850Sstevel@tonic-gate * unit address strings that represent same-slot use: "DD" and "DD,". 5860Sstevel@tonic-gate * The first compare uses strcmp, the second uses strncmp. 5870Sstevel@tonic-gate */ 5880Sstevel@tonic-gate s1 = ddi_get_name_addr(rdip); 5890Sstevel@tonic-gate if (s1 == NULL) 5900Sstevel@tonic-gate goto newcpu; 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate buf1 = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* strcmp */ 5930Sstevel@tonic-gate buf2 = kmem_alloc(MAXNAMELEN, KM_SLEEP); /* strncmp */ 5940Sstevel@tonic-gate s1 = strcpy(buf1, s1); 5950Sstevel@tonic-gate s2 = strcpy(buf2, s1); 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate s1 = strrchr(s1, ','); 5980Sstevel@tonic-gate if (s1) { 5990Sstevel@tonic-gate *s1 = '\0'; /* have "DD,FF" */ 6000Sstevel@tonic-gate s1 = buf1; /* search via strcmp "DD" */ 6010Sstevel@tonic-gate 6020Sstevel@tonic-gate s2 = strrchr(s2, ','); 6030Sstevel@tonic-gate *(s2 + 1) = '\0'; 6040Sstevel@tonic-gate s2 = buf2; 6050Sstevel@tonic-gate l2 = strlen(s2); /* search via strncmp "DD," */ 6060Sstevel@tonic-gate } else { 6070Sstevel@tonic-gate (void) strcat(s2, ","); /* have "DD" */ 6080Sstevel@tonic-gate l2 = strlen(s2); /* search via strncmp "DD," */ 6090Sstevel@tonic-gate } 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate /* 6120Sstevel@tonic-gate * Search the established ino list for devinfo nodes bound 6130Sstevel@tonic-gate * to an ino that matches one of the slot use strings. 6140Sstevel@tonic-gate */ 6150Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex)); 6160Sstevel@tonic-gate for (sino_p = ib_p->ib_ino_lst; sino_p; sino_p = sino_p->ino_next) { 6170Sstevel@tonic-gate /* skip self and non-established */ 6180Sstevel@tonic-gate if ((sino_p == ino_p) || (sino_p->ino_established == 0)) 6190Sstevel@tonic-gate continue; 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate /* skip non-siblings */ 6220Sstevel@tonic-gate sdip = sino_p->ino_ih_head->ih_dip; 6230Sstevel@tonic-gate psdip = ddi_get_parent(sdip); 6240Sstevel@tonic-gate if (psdip != prdip) 6250Sstevel@tonic-gate continue; 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate /* must be psycho driver parent (not ebus) */ 6280Sstevel@tonic-gate if (strcmp(ddi_driver_name(psdip), "pcipsy") != 0) 6290Sstevel@tonic-gate continue; 6300Sstevel@tonic-gate 6310Sstevel@tonic-gate s3 = ddi_get_name_addr(sdip); 6320Sstevel@tonic-gate if ((s1 && (strcmp(s1, s3) == 0)) || 6330Sstevel@tonic-gate (strncmp(s2, s3, l2) == 0)) { 6340Sstevel@tonic-gate extern int intr_dist_debug; 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate if (intr_dist_debug) 6370Sstevel@tonic-gate cmn_err(CE_CONT, "intr_dist: " 6380Sstevel@tonic-gate "pcipsy`pci_intr_dist_cpuid " 6390Sstevel@tonic-gate "%s#%d %s: cpu %d established " 6400Sstevel@tonic-gate "by %s#%d %s\n", ddi_driver_name(rdip), 6410Sstevel@tonic-gate ddi_get_instance(rdip), 6420Sstevel@tonic-gate ddi_deviname(rdip, buf1), sino_p->ino_cpuid, 6430Sstevel@tonic-gate ddi_driver_name(sdip), 6440Sstevel@tonic-gate ddi_get_instance(sdip), 6450Sstevel@tonic-gate ddi_deviname(sdip, buf2)); 6460Sstevel@tonic-gate break; 6470Sstevel@tonic-gate } 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate /* If a slot use match is found then use established cpu */ 6510Sstevel@tonic-gate if (sino_p) { 6520Sstevel@tonic-gate cpu_id = sino_p->ino_cpuid; /* target established cpu */ 6530Sstevel@tonic-gate goto out; 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate newcpu: cpu_id = intr_dist_cpuid(); /* target new cpu */ 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate out: if (buf1) 6590Sstevel@tonic-gate kmem_free(buf1, MAXNAMELEN); 6600Sstevel@tonic-gate if (buf2) 6610Sstevel@tonic-gate kmem_free(buf2, MAXNAMELEN); 6620Sstevel@tonic-gate return (cpu_id); 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate /*ARGSUSED*/ 667*1924Sarutz static void 668*1924Sarutz cb_thermal_timeout(void *arg) 669*1924Sarutz { 670*1924Sarutz do_shutdown(); 671*1924Sarutz 672*1924Sarutz /* 673*1924Sarutz * In case do_shutdown() fails to halt the system. 674*1924Sarutz */ 675*1924Sarutz (void) timeout((void(*)(void *))power_down, NULL, 676*1924Sarutz thermal_powerdown_delay * hz); 677*1924Sarutz } 678*1924Sarutz 679*1924Sarutz /* 680*1924Sarutz * High-level handler for psycho's CBNINTR_THERMAL interrupt. 681*1924Sarutz * 682*1924Sarutz * Use timeout(9f) to implement the core functionality so that the 683*1924Sarutz * timeout(9f) function can sleep, if needed. 684*1924Sarutz */ 685*1924Sarutz /*ARGSUSED*/ 6860Sstevel@tonic-gate uint_t 6870Sstevel@tonic-gate cb_thermal_intr(caddr_t a) 6880Sstevel@tonic-gate { 6890Sstevel@tonic-gate cmn_err(CE_WARN, "pci: Thermal warning detected!\n"); 6900Sstevel@tonic-gate if (pci_thermal_intr_fatal) { 691*1924Sarutz (void) timeout(cb_thermal_timeout, NULL, 0); 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate return (DDI_INTR_CLAIMED); 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate void 6970Sstevel@tonic-gate pci_cb_teardown(pci_t *pci_p) 6980Sstevel@tonic-gate { 6990Sstevel@tonic-gate cb_t *cb_p = pci_p->pci_cb_p; 7000Sstevel@tonic-gate uint32_t mondo; 7010Sstevel@tonic-gate 7020Sstevel@tonic-gate if (pci_p->pci_thermal_interrupt != -1) { 7030Sstevel@tonic-gate mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) | 7040Sstevel@tonic-gate pci_p->pci_inos[CBNINTR_THERMAL]); 7050Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo); 7060Sstevel@tonic-gate 7070Sstevel@tonic-gate cb_disable_nintr(cb_p, CBNINTR_THERMAL, IB_INTR_WAIT); 7080Sstevel@tonic-gate rem_ivintr(mondo, NULL); 7090Sstevel@tonic-gate } 7100Sstevel@tonic-gate #ifdef _STARFIRE 7110Sstevel@tonic-gate pc_ittrans_uninit(cb_p->cb_ittrans_cookie); 7120Sstevel@tonic-gate #endif /* _STARFIRE */ 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate int 7160Sstevel@tonic-gate cb_register_intr(pci_t *pci_p) 7170Sstevel@tonic-gate { 7180Sstevel@tonic-gate uint32_t mondo; 7190Sstevel@tonic-gate 7200Sstevel@tonic-gate if (pci_p->pci_thermal_interrupt == -1) 7210Sstevel@tonic-gate return (DDI_SUCCESS); 7220Sstevel@tonic-gate 7230Sstevel@tonic-gate mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) | 7240Sstevel@tonic-gate pci_p->pci_inos[CBNINTR_THERMAL]); 7250Sstevel@tonic-gate mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, mondo); 7260Sstevel@tonic-gate 7270Sstevel@tonic-gate VERIFY(add_ivintr(mondo, pci_pil[CBNINTR_THERMAL], 7280Sstevel@tonic-gate cb_thermal_intr, (caddr_t)pci_p->pci_cb_p, 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 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 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 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 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); 7630Sstevel@tonic-gate rem_ivintr(mondo, NULL); 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 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 7780Sstevel@tonic-gate VERIFY(add_ivintr(mondo, pci_pil[inum], ecc_intr, 7790Sstevel@tonic-gate (caddr_t)eii_p, 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 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 7930Sstevel@tonic-gate rem_ivintr(mondo, NULL); 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 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 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 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 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 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 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 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 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 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 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 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 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 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 12530Sstevel@tonic-gate pci_post_uninit_child(pci_t *pci_p) 12540Sstevel@tonic-gate { 12550Sstevel@tonic-gate } 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate void 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 12920Sstevel@tonic-gate pci_pbm_teardown(pbm_t *pbm_p) 12930Sstevel@tonic-gate { 12940Sstevel@tonic-gate } 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 16111817Sarutz if (err & COMMON_ECC_UE_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 } 16241817Sarutz } else if (err & COMMON_ECC_UE_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 } 16371817Sarutz } else if (err & COMMON_ECC_UE_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 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 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 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 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 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 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 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 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 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 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 19680Sstevel@tonic-gate void 19690Sstevel@tonic-gate pci_vmem_free(iommu_t *iommu_p, ddi_dma_impl_t *mp, void *dvma_addr, 19700Sstevel@tonic-gate size_t npages) 19710Sstevel@tonic-gate { 19720Sstevel@tonic-gate pci_vmem_do_free(iommu_p, dvma_addr, npages, 19730Sstevel@tonic-gate (mp->dmai_flags & DMAI_FLAGS_VMEMCACHE)); 19740Sstevel@tonic-gate } 19750Sstevel@tonic-gate 19760Sstevel@tonic-gate 19770Sstevel@tonic-gate /* 19780Sstevel@tonic-gate * NOTE: This call is only used by legacy systems (eg. E250 and E450) that 19790Sstevel@tonic-gate * require unregistering the pci driver's thermal intrerrupt handler before 19800Sstevel@tonic-gate * they can register their own. 19810Sstevel@tonic-gate */ 19820Sstevel@tonic-gate void 19830Sstevel@tonic-gate pci_thermal_rem_intr(dev_info_t *rdip, uint_t inum) 19840Sstevel@tonic-gate { 19850Sstevel@tonic-gate pci_t *pci_p; 19860Sstevel@tonic-gate dev_info_t *pdip; 19870Sstevel@tonic-gate uint32_t dev_mondo, pci_mondo; 19880Sstevel@tonic-gate int instance; 19890Sstevel@tonic-gate 19900Sstevel@tonic-gate for (pdip = ddi_get_parent(rdip); pdip; pdip = ddi_get_parent(pdip)) { 19910Sstevel@tonic-gate if (strcmp(ddi_driver_name(pdip), "pcipsy") == 0) 19920Sstevel@tonic-gate break; 19930Sstevel@tonic-gate } 19940Sstevel@tonic-gate 19950Sstevel@tonic-gate if (!pdip) { 19960Sstevel@tonic-gate cmn_err(CE_WARN, "pci_thermal_rem_intr() no pcipsy parent\n"); 19970Sstevel@tonic-gate return; 19980Sstevel@tonic-gate } 19990Sstevel@tonic-gate 20000Sstevel@tonic-gate instance = ddi_get_instance(pdip); 20010Sstevel@tonic-gate pci_p = get_pci_soft_state(instance); 20020Sstevel@tonic-gate 20030Sstevel@tonic-gate /* Calculate the requesting device's mondo */ 20040Sstevel@tonic-gate dev_mondo = pci_xlate_intr(pci_p->pci_dip, rdip, pci_p->pci_ib_p, 2005693Sgovinda IB_MONDO_TO_INO(i_ddi_get_inum(rdip, inum))); 20060Sstevel@tonic-gate 20070Sstevel@tonic-gate /* get pci's thermal mondo */ 20080Sstevel@tonic-gate pci_mondo = ((pci_p->pci_cb_p->cb_ign << PCI_INO_BITS) | 20090Sstevel@tonic-gate pci_p->pci_inos[CBNINTR_THERMAL]); 20100Sstevel@tonic-gate pci_mondo = CB_MONDO_TO_XMONDO(pci_p->pci_cb_p, pci_mondo); 20110Sstevel@tonic-gate 20120Sstevel@tonic-gate if (pci_mondo == dev_mondo) { 20130Sstevel@tonic-gate DEBUG2(DBG_ATTACH, rdip, "pci_thermal_rem_intr unregistered " 20140Sstevel@tonic-gate "for dip=%s%d:", ddi_driver_name(rdip), 20150Sstevel@tonic-gate ddi_get_instance(rdip)); 20160Sstevel@tonic-gate rem_ivintr(pci_mondo, NULL); 20170Sstevel@tonic-gate } 20180Sstevel@tonic-gate } 2019