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 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/kmem.h> 310Sstevel@tonic-gate #include <sys/conf.h> 320Sstevel@tonic-gate #include <sys/ddi.h> 330Sstevel@tonic-gate #include <sys/sunddi.h> 34*27Sjchu #include <sys/fm/protocol.h> 35*27Sjchu #include <sys/fm/util.h> 360Sstevel@tonic-gate #include <sys/modctl.h> 370Sstevel@tonic-gate #include <sys/disp.h> 380Sstevel@tonic-gate #include <sys/stat.h> 390Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 400Sstevel@tonic-gate #include <sys/vmem.h> 410Sstevel@tonic-gate #include <sys/iommutsb.h> 420Sstevel@tonic-gate #include <sys/cpuvar.h> 43*27Sjchu #include <sys/ivintr.h> 440Sstevel@tonic-gate #include <px_obj.h> 450Sstevel@tonic-gate #include <pcie_pwr.h> 460Sstevel@tonic-gate #include "px_tools_var.h" 470Sstevel@tonic-gate #include <px_regs.h> 480Sstevel@tonic-gate #include <px_csr.h> 49*27Sjchu #include <sys/machsystm.h> 500Sstevel@tonic-gate #include "px_lib4u.h" 51*27Sjchu #include "px_err.h" 520Sstevel@tonic-gate 530Sstevel@tonic-gate #pragma weak jbus_stst_order 540Sstevel@tonic-gate 550Sstevel@tonic-gate extern void jbus_stst_order(); 560Sstevel@tonic-gate 570Sstevel@tonic-gate ulong_t px_mmu_dvma_end = 0xfffffffful; 580Sstevel@tonic-gate uint_t px_ranges_phi_mask = 0xfffffffful; 590Sstevel@tonic-gate 600Sstevel@tonic-gate static int px_goto_l23ready(px_t *px_p); 610Sstevel@tonic-gate static uint32_t px_identity_chip(px_t *px_p); 62*27Sjchu static void px_lib_clr_errs(px_t *px_p, px_pec_t *pec_p); 63*27Sjchu 64*27Sjchu /* 65*27Sjchu * px_lib_map_registers 66*27Sjchu * 67*27Sjchu * This function is called from the attach routine to map the registers 68*27Sjchu * accessed by this driver. 69*27Sjchu * 70*27Sjchu * used by: px_attach() 71*27Sjchu * 72*27Sjchu * return value: DDI_FAILURE on failure 73*27Sjchu */ 74*27Sjchu int 75*27Sjchu px_lib_map_regs(pxu_t *pxu_p, dev_info_t *dip) 76*27Sjchu { 77*27Sjchu ddi_device_acc_attr_t attr; 78*27Sjchu px_reg_bank_t reg_bank = PX_REG_CSR; 79*27Sjchu 80*27Sjchu DBG(DBG_ATTACH, dip, "px_lib_map_regs: pxu_p:0x%p, dip 0x%p\n", 81*27Sjchu pxu_p, dip); 82*27Sjchu 83*27Sjchu attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 84*27Sjchu attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 85*27Sjchu attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 86*27Sjchu 87*27Sjchu /* 88*27Sjchu * PCI CSR Base 89*27Sjchu */ 90*27Sjchu if (ddi_regs_map_setup(dip, reg_bank, &pxu_p->px_address[reg_bank], 91*27Sjchu 0, 0, &attr, &pxu_p->px_ac[reg_bank]) != DDI_SUCCESS) { 92*27Sjchu goto fail; 93*27Sjchu } 94*27Sjchu 95*27Sjchu reg_bank++; 96*27Sjchu 97*27Sjchu /* 98*27Sjchu * XBUS CSR Base 99*27Sjchu */ 100*27Sjchu if (ddi_regs_map_setup(dip, reg_bank, &pxu_p->px_address[reg_bank], 101*27Sjchu 0, 0, &attr, &pxu_p->px_ac[reg_bank]) != DDI_SUCCESS) { 102*27Sjchu goto fail; 103*27Sjchu } 104*27Sjchu 105*27Sjchu pxu_p->px_address[reg_bank] -= FIRE_CONTROL_STATUS; 106*27Sjchu 107*27Sjchu done: 108*27Sjchu for (; reg_bank >= PX_REG_CSR; reg_bank--) { 109*27Sjchu DBG(DBG_ATTACH, dip, "reg_bank 0x%x address 0x%p\n", 110*27Sjchu reg_bank, pxu_p->px_address[reg_bank]); 111*27Sjchu } 112*27Sjchu 113*27Sjchu return (DDI_SUCCESS); 114*27Sjchu 115*27Sjchu fail: 116*27Sjchu cmn_err(CE_WARN, "%s%d: unable to map reg entry %d\n", 117*27Sjchu ddi_driver_name(dip), ddi_get_instance(dip), reg_bank); 118*27Sjchu 119*27Sjchu for (reg_bank--; reg_bank >= PX_REG_CSR; reg_bank--) { 120*27Sjchu pxu_p->px_address[reg_bank] = NULL; 121*27Sjchu ddi_regs_map_free(&pxu_p->px_ac[reg_bank]); 122*27Sjchu } 123*27Sjchu 124*27Sjchu return (DDI_FAILURE); 125*27Sjchu } 126*27Sjchu 127*27Sjchu /* 128*27Sjchu * px_lib_unmap_regs: 129*27Sjchu * 130*27Sjchu * This routine unmaps the registers mapped by map_px_registers. 131*27Sjchu * 132*27Sjchu * used by: px_detach(), and error conditions in px_attach() 133*27Sjchu * 134*27Sjchu * return value: none 135*27Sjchu */ 136*27Sjchu void 137*27Sjchu px_lib_unmap_regs(pxu_t *pxu_p) 138*27Sjchu { 139*27Sjchu int i; 140*27Sjchu 141*27Sjchu for (i = 0; i < PX_REG_MAX; i++) { 142*27Sjchu if (pxu_p->px_ac[i]) 143*27Sjchu ddi_regs_map_free(&pxu_p->px_ac[i]); 144*27Sjchu } 145*27Sjchu } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate int 1480Sstevel@tonic-gate px_lib_dev_init(dev_info_t *dip, devhandle_t *dev_hdl) 1490Sstevel@tonic-gate { 1500Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 151*27Sjchu caddr_t xbc_csr_base, csr_base; 1520Sstevel@tonic-gate px_dvma_range_prop_t px_dvma_range; 1530Sstevel@tonic-gate uint32_t chip_id; 1540Sstevel@tonic-gate pxu_t *pxu_p; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_dev_init: dip 0x%p\n", dip); 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate if ((chip_id = px_identity_chip(px_p)) == PX_CHIP_UNIDENTIFIED) 1590Sstevel@tonic-gate return (DDI_FAILURE); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate switch (chip_id) { 1620Sstevel@tonic-gate case FIRE_VER_10: 1630Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "FIRE Hardware Version 1.0\n"); 1640Sstevel@tonic-gate break; 1650Sstevel@tonic-gate case FIRE_VER_20: 1660Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "FIRE Hardware Version 2.0\n"); 1670Sstevel@tonic-gate break; 1680Sstevel@tonic-gate default: 169*27Sjchu cmn_err(CE_WARN, "%s%d: FIRE Hardware Version Unknown\n", 1700Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip)); 1710Sstevel@tonic-gate return (DDI_FAILURE); 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate /* 1750Sstevel@tonic-gate * Allocate platform specific structure and link it to 1760Sstevel@tonic-gate * the px state structure. 1770Sstevel@tonic-gate */ 1780Sstevel@tonic-gate pxu_p = kmem_zalloc(sizeof (pxu_t), KM_SLEEP); 1790Sstevel@tonic-gate pxu_p->chip_id = chip_id; 1800Sstevel@tonic-gate pxu_p->portid = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1810Sstevel@tonic-gate "portid", -1); 1820Sstevel@tonic-gate 183*27Sjchu /* Map in the registers */ 184*27Sjchu if (px_lib_map_regs(pxu_p, dip) == DDI_FAILURE) { 185*27Sjchu kmem_free(pxu_p, sizeof (pxu_t)); 186*27Sjchu 187*27Sjchu return (DDI_FAILURE); 188*27Sjchu } 189*27Sjchu 190*27Sjchu xbc_csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC]; 191*27Sjchu csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR]; 192*27Sjchu 1930Sstevel@tonic-gate pxu_p->tsb_cookie = iommu_tsb_alloc(pxu_p->portid); 1940Sstevel@tonic-gate pxu_p->tsb_size = iommu_tsb_cookie_to_size(pxu_p->tsb_cookie); 1950Sstevel@tonic-gate pxu_p->tsb_vaddr = iommu_tsb_cookie_to_va(pxu_p->tsb_cookie); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate /* 1980Sstevel@tonic-gate * Create "virtual-dma" property to support child devices 1990Sstevel@tonic-gate * needing to know DVMA range. 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate px_dvma_range.dvma_base = (uint32_t)px_mmu_dvma_end + 1 2020Sstevel@tonic-gate - ((pxu_p->tsb_size >> 3) << MMU_PAGE_SHIFT); 2030Sstevel@tonic-gate px_dvma_range.dvma_len = (uint32_t) 2040Sstevel@tonic-gate px_mmu_dvma_end - px_dvma_range.dvma_base + 1; 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, 2070Sstevel@tonic-gate "virtual-dma", (caddr_t)&px_dvma_range, 2080Sstevel@tonic-gate sizeof (px_dvma_range_prop_t)); 2090Sstevel@tonic-gate /* 2100Sstevel@tonic-gate * Initilize all fire hardware specific blocks. 2110Sstevel@tonic-gate */ 2120Sstevel@tonic-gate hvio_cb_init(xbc_csr_base, pxu_p); 2130Sstevel@tonic-gate hvio_ib_init(csr_base, pxu_p); 2140Sstevel@tonic-gate hvio_pec_init(csr_base, pxu_p); 2150Sstevel@tonic-gate hvio_mmu_init(csr_base, pxu_p); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate px_p->px_plat_p = (void *)pxu_p; 2180Sstevel@tonic-gate 219*27Sjchu /* 220*27Sjchu * Initialize all the interrupt handlers 221*27Sjchu */ 222*27Sjchu px_err_reg_enable(px_p, PX_ERR_JBC); 223*27Sjchu px_err_reg_enable(px_p, PX_ERR_MMU); 224*27Sjchu px_err_reg_enable(px_p, PX_ERR_IMU); 225*27Sjchu px_err_reg_enable(px_p, PX_ERR_TLU_UE); 226*27Sjchu px_err_reg_enable(px_p, PX_ERR_TLU_CE); 227*27Sjchu px_err_reg_enable(px_p, PX_ERR_TLU_OE); 228*27Sjchu px_err_reg_enable(px_p, PX_ERR_ILU); 229*27Sjchu px_err_reg_enable(px_p, PX_ERR_LPU_LINK); 230*27Sjchu px_err_reg_enable(px_p, PX_ERR_LPU_PHY); 231*27Sjchu px_err_reg_enable(px_p, PX_ERR_LPU_RX); 232*27Sjchu px_err_reg_enable(px_p, PX_ERR_LPU_TX); 233*27Sjchu px_err_reg_enable(px_p, PX_ERR_LPU_LTSSM); 234*27Sjchu px_err_reg_enable(px_p, PX_ERR_LPU_GIGABLZ); 235*27Sjchu 2360Sstevel@tonic-gate /* Initilize device handle */ 2370Sstevel@tonic-gate *dev_hdl = (devhandle_t)csr_base; 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_dev_init: dev_hdl 0x%llx\n", *dev_hdl); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate return (DDI_SUCCESS); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate int 2450Sstevel@tonic-gate px_lib_dev_fini(dev_info_t *dip) 2460Sstevel@tonic-gate { 2470Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 2480Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate DBG(DBG_DETACH, dip, "px_lib_dev_fini: dip 0x%p\n", dip); 2510Sstevel@tonic-gate 252*27Sjchu /* 253*27Sjchu * Deinitialize all the interrupt handlers 254*27Sjchu */ 255*27Sjchu px_err_reg_disable(px_p, PX_ERR_JBC); 256*27Sjchu px_err_reg_disable(px_p, PX_ERR_MMU); 257*27Sjchu px_err_reg_disable(px_p, PX_ERR_IMU); 258*27Sjchu px_err_reg_disable(px_p, PX_ERR_TLU_UE); 259*27Sjchu px_err_reg_disable(px_p, PX_ERR_TLU_CE); 260*27Sjchu px_err_reg_disable(px_p, PX_ERR_TLU_OE); 261*27Sjchu px_err_reg_disable(px_p, PX_ERR_ILU); 262*27Sjchu px_err_reg_disable(px_p, PX_ERR_LPU_LINK); 263*27Sjchu px_err_reg_disable(px_p, PX_ERR_LPU_PHY); 264*27Sjchu px_err_reg_disable(px_p, PX_ERR_LPU_RX); 265*27Sjchu px_err_reg_disable(px_p, PX_ERR_LPU_TX); 266*27Sjchu px_err_reg_disable(px_p, PX_ERR_LPU_LTSSM); 267*27Sjchu px_err_reg_disable(px_p, PX_ERR_LPU_GIGABLZ); 268*27Sjchu 2690Sstevel@tonic-gate iommu_tsb_free(pxu_p->tsb_cookie); 2700Sstevel@tonic-gate 271*27Sjchu px_lib_unmap_regs((pxu_t *)px_p->px_plat_p); 272*27Sjchu kmem_free(px_p->px_plat_p, sizeof (pxu_t)); 2730Sstevel@tonic-gate px_p->px_plat_p = NULL; 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate return (DDI_SUCCESS); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate /*ARGSUSED*/ 2790Sstevel@tonic-gate int 2800Sstevel@tonic-gate px_lib_intr_devino_to_sysino(dev_info_t *dip, devino_t devino, 2810Sstevel@tonic-gate sysino_t *sysino) 2820Sstevel@tonic-gate { 2830Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 2840Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 2850Sstevel@tonic-gate uint64_t ret; 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: dip 0x%p " 2880Sstevel@tonic-gate "devino 0x%x\n", dip, devino); 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate if ((ret = hvio_intr_devino_to_sysino(DIP_TO_HANDLE(dip), 2910Sstevel@tonic-gate pxu_p, devino, sysino)) != H_EOK) { 2920Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, 2930Sstevel@tonic-gate "hvio_intr_devino_to_sysino failed, ret 0x%lx\n", ret); 2940Sstevel@tonic-gate return (DDI_FAILURE); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: sysino 0x%llx\n", 2980Sstevel@tonic-gate *sysino); 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate return (DDI_SUCCESS); 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate /*ARGSUSED*/ 3040Sstevel@tonic-gate int 3050Sstevel@tonic-gate px_lib_intr_getvalid(dev_info_t *dip, sysino_t sysino, 3060Sstevel@tonic-gate intr_valid_state_t *intr_valid_state) 3070Sstevel@tonic-gate { 3080Sstevel@tonic-gate uint64_t ret; 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: dip 0x%p sysino 0x%llx\n", 3110Sstevel@tonic-gate dip, sysino); 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate if ((ret = hvio_intr_getvalid(DIP_TO_HANDLE(dip), 3140Sstevel@tonic-gate sysino, intr_valid_state)) != H_EOK) { 3150Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_getvalid failed, ret 0x%lx\n", 3160Sstevel@tonic-gate ret); 3170Sstevel@tonic-gate return (DDI_FAILURE); 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: intr_valid_state 0x%x\n", 3210Sstevel@tonic-gate *intr_valid_state); 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate return (DDI_SUCCESS); 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /*ARGSUSED*/ 3270Sstevel@tonic-gate int 3280Sstevel@tonic-gate px_lib_intr_setvalid(dev_info_t *dip, sysino_t sysino, 3290Sstevel@tonic-gate intr_valid_state_t intr_valid_state) 3300Sstevel@tonic-gate { 3310Sstevel@tonic-gate uint64_t ret; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_setvalid: dip 0x%p sysino 0x%llx " 3340Sstevel@tonic-gate "intr_valid_state 0x%x\n", dip, sysino, intr_valid_state); 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate if ((ret = hvio_intr_setvalid(DIP_TO_HANDLE(dip), 3370Sstevel@tonic-gate sysino, intr_valid_state)) != H_EOK) { 3380Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_setvalid failed, ret 0x%lx\n", 3390Sstevel@tonic-gate ret); 3400Sstevel@tonic-gate return (DDI_FAILURE); 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate return (DDI_SUCCESS); 3440Sstevel@tonic-gate } 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate /*ARGSUSED*/ 3470Sstevel@tonic-gate int 3480Sstevel@tonic-gate px_lib_intr_getstate(dev_info_t *dip, sysino_t sysino, 3490Sstevel@tonic-gate intr_state_t *intr_state) 3500Sstevel@tonic-gate { 3510Sstevel@tonic-gate uint64_t ret; 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: dip 0x%p sysino 0x%llx\n", 3540Sstevel@tonic-gate dip, sysino); 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate if ((ret = hvio_intr_getstate(DIP_TO_HANDLE(dip), 3570Sstevel@tonic-gate sysino, intr_state)) != H_EOK) { 3580Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_getstate failed, ret 0x%lx\n", 3590Sstevel@tonic-gate ret); 3600Sstevel@tonic-gate return (DDI_FAILURE); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: intr_state 0x%x\n", 3640Sstevel@tonic-gate *intr_state); 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate return (DDI_SUCCESS); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate /*ARGSUSED*/ 3700Sstevel@tonic-gate int 3710Sstevel@tonic-gate px_lib_intr_setstate(dev_info_t *dip, sysino_t sysino, 3720Sstevel@tonic-gate intr_state_t intr_state) 3730Sstevel@tonic-gate { 3740Sstevel@tonic-gate uint64_t ret; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_setstate: dip 0x%p sysino 0x%llx " 3770Sstevel@tonic-gate "intr_state 0x%x\n", dip, sysino, intr_state); 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate if ((ret = hvio_intr_setstate(DIP_TO_HANDLE(dip), 3800Sstevel@tonic-gate sysino, intr_state)) != H_EOK) { 3810Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_setstate failed, ret 0x%lx\n", 3820Sstevel@tonic-gate ret); 3830Sstevel@tonic-gate return (DDI_FAILURE); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate return (DDI_SUCCESS); 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /*ARGSUSED*/ 3900Sstevel@tonic-gate int 3910Sstevel@tonic-gate px_lib_intr_gettarget(dev_info_t *dip, sysino_t sysino, cpuid_t *cpuid) 3920Sstevel@tonic-gate { 3930Sstevel@tonic-gate uint64_t ret; 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: dip 0x%p sysino 0x%llx\n", 3960Sstevel@tonic-gate dip, sysino); 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate if ((ret = hvio_intr_gettarget(DIP_TO_HANDLE(dip), 3990Sstevel@tonic-gate sysino, cpuid)) != H_EOK) { 4000Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_gettarget failed, ret 0x%lx\n", 4010Sstevel@tonic-gate ret); 4020Sstevel@tonic-gate return (DDI_FAILURE); 4030Sstevel@tonic-gate } 4040Sstevel@tonic-gate 4050Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: cpuid 0x%x\n", cpuid); 4060Sstevel@tonic-gate 4070Sstevel@tonic-gate return (DDI_SUCCESS); 4080Sstevel@tonic-gate } 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate /*ARGSUSED*/ 4110Sstevel@tonic-gate int 4120Sstevel@tonic-gate px_lib_intr_settarget(dev_info_t *dip, sysino_t sysino, cpuid_t cpuid) 4130Sstevel@tonic-gate { 4140Sstevel@tonic-gate uint64_t ret; 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_settarget: dip 0x%p sysino 0x%llx " 4170Sstevel@tonic-gate "cpuid 0x%x\n", dip, sysino, cpuid); 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate if ((ret = hvio_intr_settarget(DIP_TO_HANDLE(dip), 4200Sstevel@tonic-gate sysino, cpuid)) != H_EOK) { 4210Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_settarget failed, ret 0x%lx\n", 4220Sstevel@tonic-gate ret); 4230Sstevel@tonic-gate return (DDI_FAILURE); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate return (DDI_SUCCESS); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate /*ARGSUSED*/ 4300Sstevel@tonic-gate int 4310Sstevel@tonic-gate px_lib_intr_reset(dev_info_t *dip) 4320Sstevel@tonic-gate { 4330Sstevel@tonic-gate devino_t ino; 4340Sstevel@tonic-gate sysino_t sysino; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_reset: dip 0x%p\n", dip); 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate /* Reset all Interrupts */ 4390Sstevel@tonic-gate for (ino = 0; ino < INTERRUPT_MAPPING_ENTRIES; ino++) { 4400Sstevel@tonic-gate if (px_lib_intr_devino_to_sysino(dip, ino, 4410Sstevel@tonic-gate &sysino) != DDI_SUCCESS) 4420Sstevel@tonic-gate return (BF_FATAL); 4430Sstevel@tonic-gate 4440Sstevel@tonic-gate if (px_lib_intr_setstate(dip, sysino, 4450Sstevel@tonic-gate INTR_IDLE_STATE) != DDI_SUCCESS) 4460Sstevel@tonic-gate return (BF_FATAL); 4470Sstevel@tonic-gate } 4480Sstevel@tonic-gate 4490Sstevel@tonic-gate return (BF_NONE); 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate /*ARGSUSED*/ 4530Sstevel@tonic-gate int 4540Sstevel@tonic-gate px_lib_iommu_map(dev_info_t *dip, tsbid_t tsbid, pages_t pages, 4550Sstevel@tonic-gate io_attributes_t io_attributes, void *addr, size_t pfn_index, 4560Sstevel@tonic-gate int flag) 4570Sstevel@tonic-gate { 4580Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 4590Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 4600Sstevel@tonic-gate uint64_t ret; 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: dip 0x%p tsbid 0x%llx " 4630Sstevel@tonic-gate "pages 0x%x atrr 0x%x addr 0x%p pfn_index 0x%llx, flag 0x%x\n", 4640Sstevel@tonic-gate dip, tsbid, pages, io_attributes, addr, pfn_index, flag); 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate if ((ret = hvio_iommu_map(px_p->px_dev_hdl, pxu_p, tsbid, pages, 4670Sstevel@tonic-gate io_attributes, addr, pfn_index, flag)) != H_EOK) { 4680Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, 4690Sstevel@tonic-gate "px_lib_iommu_map failed, ret 0x%lx\n", ret); 4700Sstevel@tonic-gate return (DDI_FAILURE); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate return (DDI_SUCCESS); 4740Sstevel@tonic-gate } 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate /*ARGSUSED*/ 4770Sstevel@tonic-gate int 4780Sstevel@tonic-gate px_lib_iommu_demap(dev_info_t *dip, tsbid_t tsbid, pages_t pages) 4790Sstevel@tonic-gate { 4800Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 4810Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 4820Sstevel@tonic-gate uint64_t ret; 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: dip 0x%p tsbid 0x%llx " 4850Sstevel@tonic-gate "pages 0x%x\n", dip, tsbid, pages); 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate if ((ret = hvio_iommu_demap(px_p->px_dev_hdl, pxu_p, tsbid, pages)) 4880Sstevel@tonic-gate != H_EOK) { 4890Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, 4900Sstevel@tonic-gate "px_lib_iommu_demap failed, ret 0x%lx\n", ret); 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate return (DDI_FAILURE); 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate return (DDI_SUCCESS); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate /*ARGSUSED*/ 4990Sstevel@tonic-gate int 5000Sstevel@tonic-gate px_lib_iommu_getmap(dev_info_t *dip, tsbid_t tsbid, 5010Sstevel@tonic-gate io_attributes_t *attributes_p, r_addr_t *r_addr_p) 5020Sstevel@tonic-gate { 5030Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 5040Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 5050Sstevel@tonic-gate uint64_t ret; 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: dip 0x%p tsbid 0x%llx\n", 5080Sstevel@tonic-gate dip, tsbid); 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate if ((ret = hvio_iommu_getmap(DIP_TO_HANDLE(dip), pxu_p, tsbid, 5110Sstevel@tonic-gate attributes_p, r_addr_p)) != H_EOK) { 5120Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, 5130Sstevel@tonic-gate "hvio_iommu_getmap failed, ret 0x%lx\n", ret); 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate return ((ret == H_ENOMAP) ? DDI_DMA_NOMAPPING:DDI_FAILURE); 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: attr 0x%x r_addr 0x%llx\n", 5190Sstevel@tonic-gate *attributes_p, *r_addr_p); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate return (DDI_SUCCESS); 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate /* 5260Sstevel@tonic-gate * Checks dma attributes against system bypass ranges 5270Sstevel@tonic-gate * The bypass range is determined by the hardware. Return them so the 5280Sstevel@tonic-gate * common code can do generic checking against them. 5290Sstevel@tonic-gate */ 5300Sstevel@tonic-gate /*ARGSUSED*/ 5310Sstevel@tonic-gate int 5320Sstevel@tonic-gate px_lib_dma_bypass_rngchk(ddi_dma_attr_t *attrp, uint64_t *lo_p, uint64_t *hi_p) 5330Sstevel@tonic-gate { 5340Sstevel@tonic-gate *lo_p = MMU_BYPASS_BASE; 5350Sstevel@tonic-gate *hi_p = MMU_BYPASS_END; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate return (DDI_SUCCESS); 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate /*ARGSUSED*/ 5420Sstevel@tonic-gate int 5430Sstevel@tonic-gate px_lib_iommu_getbypass(dev_info_t *dip, r_addr_t ra, 5440Sstevel@tonic-gate io_attributes_t io_attributes, io_addr_t *io_addr_p) 5450Sstevel@tonic-gate { 5460Sstevel@tonic-gate uint64_t ret; 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: dip 0x%p ra 0x%llx " 5490Sstevel@tonic-gate "attr 0x%x\n", dip, ra, io_attributes); 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate if ((ret = hvio_iommu_getbypass(DIP_TO_HANDLE(dip), ra, 5520Sstevel@tonic-gate io_attributes, io_addr_p)) != H_EOK) { 5530Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, 5540Sstevel@tonic-gate "hvio_iommu_getbypass failed, ret 0x%lx\n", ret); 5550Sstevel@tonic-gate return (DDI_FAILURE); 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate 5580Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: io_addr 0x%llx\n", 5590Sstevel@tonic-gate *io_addr_p); 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate return (DDI_SUCCESS); 5620Sstevel@tonic-gate } 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate /* 5650Sstevel@tonic-gate * bus dma sync entry point. 5660Sstevel@tonic-gate */ 5670Sstevel@tonic-gate /*ARGSUSED*/ 5680Sstevel@tonic-gate int 5690Sstevel@tonic-gate px_lib_dma_sync(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle, 5700Sstevel@tonic-gate off_t off, size_t len, uint_t cache_flags) 5710Sstevel@tonic-gate { 5720Sstevel@tonic-gate ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: dip 0x%p rdip 0x%p " 5750Sstevel@tonic-gate "handle 0x%llx off 0x%x len 0x%x flags 0x%x\n", 5760Sstevel@tonic-gate dip, rdip, handle, off, len, cache_flags); 5770Sstevel@tonic-gate 5780Sstevel@tonic-gate /* 5790Sstevel@tonic-gate * jbus_stst_order is found only in certain cpu modules. 5800Sstevel@tonic-gate * Just return success if not present. 5810Sstevel@tonic-gate */ 5820Sstevel@tonic-gate if (&jbus_stst_order == NULL) 5830Sstevel@tonic-gate return (DDI_SUCCESS); 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate if (!(mp->dmai_flags & DMAI_FLAGS_INUSE)) { 586*27Sjchu cmn_err(CE_WARN, "%s%d: Unbound dma handle %p.", 587*27Sjchu ddi_driver_name(rdip), ddi_get_instance(rdip), (void *)mp); 588*27Sjchu 5890Sstevel@tonic-gate return (DDI_FAILURE); 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate if (mp->dmai_flags & DMAI_FLAGS_NOSYNC) 5930Sstevel@tonic-gate return (DDI_SUCCESS); 5940Sstevel@tonic-gate 5950Sstevel@tonic-gate /* 5960Sstevel@tonic-gate * No flush needed when sending data from memory to device. 5970Sstevel@tonic-gate * Nothing to do to "sync" memory to what device would already see. 5980Sstevel@tonic-gate */ 5990Sstevel@tonic-gate if (!(mp->dmai_rflags & DDI_DMA_READ) || 6000Sstevel@tonic-gate ((cache_flags & PX_DMA_SYNC_DDI_FLAGS) == DDI_DMA_SYNC_FORDEV)) 6010Sstevel@tonic-gate return (DDI_SUCCESS); 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate /* 6040Sstevel@tonic-gate * Perform necessary cpu workaround to ensure jbus ordering. 6050Sstevel@tonic-gate * CPU's internal "invalidate FIFOs" are flushed. 6060Sstevel@tonic-gate */ 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate #if !defined(lint) 6090Sstevel@tonic-gate kpreempt_disable(); 6100Sstevel@tonic-gate #endif 6110Sstevel@tonic-gate jbus_stst_order(); 6120Sstevel@tonic-gate #if !defined(lint) 6130Sstevel@tonic-gate kpreempt_enable(); 6140Sstevel@tonic-gate #endif 6150Sstevel@tonic-gate return (DDI_SUCCESS); 6160Sstevel@tonic-gate } 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate /* 6190Sstevel@tonic-gate * MSIQ Functions: 6200Sstevel@tonic-gate */ 6210Sstevel@tonic-gate /*ARGSUSED*/ 6220Sstevel@tonic-gate int 6230Sstevel@tonic-gate px_lib_msiq_init(dev_info_t *dip) 6240Sstevel@tonic-gate { 6250Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 6260Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 6270Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 6280Sstevel@tonic-gate caddr_t msiq_addr; 6290Sstevel@tonic-gate px_dvma_addr_t pg_index; 6300Sstevel@tonic-gate size_t size; 6310Sstevel@tonic-gate int ret; 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_init: dip 0x%p\n", dip); 6340Sstevel@tonic-gate 6350Sstevel@tonic-gate /* 6360Sstevel@tonic-gate * Map the EQ memory into the Fire MMU (has to be 512KB aligned) 6370Sstevel@tonic-gate * and then initialize the base address register. 6380Sstevel@tonic-gate * 6390Sstevel@tonic-gate * Allocate entries from Fire IOMMU so that the resulting address 6400Sstevel@tonic-gate * is properly aligned. Calculate the index of the first allocated 6410Sstevel@tonic-gate * entry. Note: The size of the mapping is assumed to be a multiple 6420Sstevel@tonic-gate * of the page size. 6430Sstevel@tonic-gate */ 6440Sstevel@tonic-gate msiq_addr = (caddr_t)(((uint64_t)msiq_state_p->msiq_buf_p + 6450Sstevel@tonic-gate (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate size = msiq_state_p->msiq_cnt * 6480Sstevel@tonic-gate msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); 6490Sstevel@tonic-gate 6500Sstevel@tonic-gate pxu_p->msiq_mapped_p = vmem_xalloc(px_p->px_mmu_p->mmu_dvma_map, 6510Sstevel@tonic-gate size, (512 * 1024), 0, 0, NULL, NULL, VM_NOSLEEP | VM_BESTFIT); 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate if (pxu_p->msiq_mapped_p == NULL) 6540Sstevel@tonic-gate return (DDI_FAILURE); 6550Sstevel@tonic-gate 6560Sstevel@tonic-gate pg_index = MMU_PAGE_INDEX(px_p->px_mmu_p, 6570Sstevel@tonic-gate MMU_BTOP((ulong_t)pxu_p->msiq_mapped_p)); 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate if ((ret = px_lib_iommu_map(px_p->px_dip, PCI_TSBID(0, pg_index), 6600Sstevel@tonic-gate MMU_BTOP(size), PCI_MAP_ATTR_WRITE, (void *)msiq_addr, 0, 6610Sstevel@tonic-gate MMU_MAP_BUF)) != DDI_SUCCESS) { 6620Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 6630Sstevel@tonic-gate "hvio_msiq_init failed, ret 0x%lx\n", ret); 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate (void) px_lib_msiq_fini(dip); 6660Sstevel@tonic-gate return (DDI_FAILURE); 6670Sstevel@tonic-gate } 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate (void) hvio_msiq_init(DIP_TO_HANDLE(dip), pxu_p); 6700Sstevel@tonic-gate 6710Sstevel@tonic-gate return (DDI_SUCCESS); 6720Sstevel@tonic-gate } 6730Sstevel@tonic-gate 6740Sstevel@tonic-gate /*ARGSUSED*/ 6750Sstevel@tonic-gate int 6760Sstevel@tonic-gate px_lib_msiq_fini(dev_info_t *dip) 6770Sstevel@tonic-gate { 6780Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 6790Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 6800Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 6810Sstevel@tonic-gate px_dvma_addr_t pg_index; 6820Sstevel@tonic-gate size_t size; 6830Sstevel@tonic-gate 6840Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_fini: dip 0x%p\n", dip); 6850Sstevel@tonic-gate 6860Sstevel@tonic-gate /* 6870Sstevel@tonic-gate * Unmap and free the EQ memory that had been mapped 6880Sstevel@tonic-gate * into the Fire IOMMU. 6890Sstevel@tonic-gate */ 6900Sstevel@tonic-gate size = msiq_state_p->msiq_cnt * 6910Sstevel@tonic-gate msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate pg_index = MMU_PAGE_INDEX(px_p->px_mmu_p, 6940Sstevel@tonic-gate MMU_BTOP((ulong_t)pxu_p->msiq_mapped_p)); 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate (void) px_lib_iommu_demap(px_p->px_dip, 6970Sstevel@tonic-gate PCI_TSBID(0, pg_index), MMU_BTOP(size)); 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate /* Free the entries from the Fire MMU */ 7000Sstevel@tonic-gate vmem_xfree(px_p->px_mmu_p->mmu_dvma_map, 7010Sstevel@tonic-gate (void *)pxu_p->msiq_mapped_p, size); 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate return (DDI_SUCCESS); 7040Sstevel@tonic-gate } 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate /*ARGSUSED*/ 7070Sstevel@tonic-gate int 7080Sstevel@tonic-gate px_lib_msiq_info(dev_info_t *dip, msiqid_t msiq_id, r_addr_t *ra_p, 7090Sstevel@tonic-gate uint_t *msiq_rec_cnt_p) 7100Sstevel@tonic-gate { 7110Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 7120Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state; 7130Sstevel@tonic-gate uint64_t *msiq_addr; 7140Sstevel@tonic-gate size_t msiq_size; 7150Sstevel@tonic-gate 7160Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: dip 0x%p msiq_id 0x%x\n", 7170Sstevel@tonic-gate dip, msiq_id); 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate msiq_addr = (uint64_t *)(((uint64_t)msiq_state_p->msiq_buf_p + 7200Sstevel@tonic-gate (MMU_PAGE_SIZE - 1)) >> MMU_PAGE_SHIFT << MMU_PAGE_SHIFT); 7210Sstevel@tonic-gate msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t); 7220Sstevel@tonic-gate ra_p = (r_addr_t *)((caddr_t)msiq_addr + (msiq_id * msiq_size)); 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate *msiq_rec_cnt_p = msiq_state_p->msiq_rec_cnt; 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: ra_p 0x%p msiq_rec_cnt 0x%x\n", 7270Sstevel@tonic-gate ra_p, *msiq_rec_cnt_p); 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate return (DDI_SUCCESS); 7300Sstevel@tonic-gate } 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate /*ARGSUSED*/ 7330Sstevel@tonic-gate int 7340Sstevel@tonic-gate px_lib_msiq_getvalid(dev_info_t *dip, msiqid_t msiq_id, 7350Sstevel@tonic-gate pci_msiq_valid_state_t *msiq_valid_state) 7360Sstevel@tonic-gate { 7370Sstevel@tonic-gate uint64_t ret; 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: dip 0x%p msiq_id 0x%x\n", 7400Sstevel@tonic-gate dip, msiq_id); 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate if ((ret = hvio_msiq_getvalid(DIP_TO_HANDLE(dip), 7430Sstevel@tonic-gate msiq_id, msiq_valid_state)) != H_EOK) { 7440Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 7450Sstevel@tonic-gate "hvio_msiq_getvalid failed, ret 0x%lx\n", ret); 7460Sstevel@tonic-gate return (DDI_FAILURE); 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: msiq_valid_state 0x%x\n", 7500Sstevel@tonic-gate *msiq_valid_state); 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate return (DDI_SUCCESS); 7530Sstevel@tonic-gate } 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate /*ARGSUSED*/ 7560Sstevel@tonic-gate int 7570Sstevel@tonic-gate px_lib_msiq_setvalid(dev_info_t *dip, msiqid_t msiq_id, 7580Sstevel@tonic-gate pci_msiq_valid_state_t msiq_valid_state) 7590Sstevel@tonic-gate { 7600Sstevel@tonic-gate uint64_t ret; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setvalid: dip 0x%p msiq_id 0x%x " 7630Sstevel@tonic-gate "msiq_valid_state 0x%x\n", dip, msiq_id, msiq_valid_state); 7640Sstevel@tonic-gate 7650Sstevel@tonic-gate if ((ret = hvio_msiq_setvalid(DIP_TO_HANDLE(dip), 7660Sstevel@tonic-gate msiq_id, msiq_valid_state)) != H_EOK) { 7670Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 7680Sstevel@tonic-gate "hvio_msiq_setvalid failed, ret 0x%lx\n", ret); 7690Sstevel@tonic-gate return (DDI_FAILURE); 7700Sstevel@tonic-gate } 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate return (DDI_SUCCESS); 7730Sstevel@tonic-gate } 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate /*ARGSUSED*/ 7760Sstevel@tonic-gate int 7770Sstevel@tonic-gate px_lib_msiq_getstate(dev_info_t *dip, msiqid_t msiq_id, 7780Sstevel@tonic-gate pci_msiq_state_t *msiq_state) 7790Sstevel@tonic-gate { 7800Sstevel@tonic-gate uint64_t ret; 7810Sstevel@tonic-gate 7820Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: dip 0x%p msiq_id 0x%x\n", 7830Sstevel@tonic-gate dip, msiq_id); 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate if ((ret = hvio_msiq_getstate(DIP_TO_HANDLE(dip), 7860Sstevel@tonic-gate msiq_id, msiq_state)) != H_EOK) { 7870Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 7880Sstevel@tonic-gate "hvio_msiq_getstate failed, ret 0x%lx\n", ret); 7890Sstevel@tonic-gate return (DDI_FAILURE); 7900Sstevel@tonic-gate } 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: msiq_state 0x%x\n", 7930Sstevel@tonic-gate *msiq_state); 7940Sstevel@tonic-gate 7950Sstevel@tonic-gate return (DDI_SUCCESS); 7960Sstevel@tonic-gate } 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate /*ARGSUSED*/ 7990Sstevel@tonic-gate int 8000Sstevel@tonic-gate px_lib_msiq_setstate(dev_info_t *dip, msiqid_t msiq_id, 8010Sstevel@tonic-gate pci_msiq_state_t msiq_state) 8020Sstevel@tonic-gate { 8030Sstevel@tonic-gate uint64_t ret; 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setstate: dip 0x%p msiq_id 0x%x " 8060Sstevel@tonic-gate "msiq_state 0x%x\n", dip, msiq_id, msiq_state); 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate if ((ret = hvio_msiq_setstate(DIP_TO_HANDLE(dip), 8090Sstevel@tonic-gate msiq_id, msiq_state)) != H_EOK) { 8100Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 8110Sstevel@tonic-gate "hvio_msiq_setstate failed, ret 0x%lx\n", ret); 8120Sstevel@tonic-gate return (DDI_FAILURE); 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate 8150Sstevel@tonic-gate return (DDI_SUCCESS); 8160Sstevel@tonic-gate } 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate /*ARGSUSED*/ 8190Sstevel@tonic-gate int 8200Sstevel@tonic-gate px_lib_msiq_gethead(dev_info_t *dip, msiqid_t msiq_id, 8210Sstevel@tonic-gate msiqhead_t *msiq_head) 8220Sstevel@tonic-gate { 8230Sstevel@tonic-gate uint64_t ret; 8240Sstevel@tonic-gate 8250Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gethead: dip 0x%p msiq_id 0x%x\n", 8260Sstevel@tonic-gate dip, msiq_id); 8270Sstevel@tonic-gate 8280Sstevel@tonic-gate if ((ret = hvio_msiq_gethead(DIP_TO_HANDLE(dip), 8290Sstevel@tonic-gate msiq_id, msiq_head)) != H_EOK) { 8300Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 8310Sstevel@tonic-gate "hvio_msiq_gethead failed, ret 0x%lx\n", ret); 8320Sstevel@tonic-gate return (DDI_FAILURE); 8330Sstevel@tonic-gate } 8340Sstevel@tonic-gate 8350Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gethead: msiq_head 0x%x\n", 8360Sstevel@tonic-gate *msiq_head); 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate return (DDI_SUCCESS); 8390Sstevel@tonic-gate } 8400Sstevel@tonic-gate 8410Sstevel@tonic-gate /*ARGSUSED*/ 8420Sstevel@tonic-gate int 8430Sstevel@tonic-gate px_lib_msiq_sethead(dev_info_t *dip, msiqid_t msiq_id, 8440Sstevel@tonic-gate msiqhead_t msiq_head) 8450Sstevel@tonic-gate { 8460Sstevel@tonic-gate uint64_t ret; 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_sethead: dip 0x%p msiq_id 0x%x " 8490Sstevel@tonic-gate "msiq_head 0x%x\n", dip, msiq_id, msiq_head); 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate if ((ret = hvio_msiq_sethead(DIP_TO_HANDLE(dip), 8520Sstevel@tonic-gate msiq_id, msiq_head)) != H_EOK) { 8530Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 8540Sstevel@tonic-gate "hvio_msiq_sethead failed, ret 0x%lx\n", ret); 8550Sstevel@tonic-gate return (DDI_FAILURE); 8560Sstevel@tonic-gate } 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate return (DDI_SUCCESS); 8590Sstevel@tonic-gate } 8600Sstevel@tonic-gate 8610Sstevel@tonic-gate /*ARGSUSED*/ 8620Sstevel@tonic-gate int 8630Sstevel@tonic-gate px_lib_msiq_gettail(dev_info_t *dip, msiqid_t msiq_id, 8640Sstevel@tonic-gate msiqtail_t *msiq_tail) 8650Sstevel@tonic-gate { 8660Sstevel@tonic-gate uint64_t ret; 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: dip 0x%p msiq_id 0x%x\n", 8690Sstevel@tonic-gate dip, msiq_id); 8700Sstevel@tonic-gate 8710Sstevel@tonic-gate if ((ret = hvio_msiq_gettail(DIP_TO_HANDLE(dip), 8720Sstevel@tonic-gate msiq_id, msiq_tail)) != H_EOK) { 8730Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, 8740Sstevel@tonic-gate "hvio_msiq_gettail failed, ret 0x%lx\n", ret); 8750Sstevel@tonic-gate return (DDI_FAILURE); 8760Sstevel@tonic-gate } 8770Sstevel@tonic-gate 8780Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: msiq_tail 0x%x\n", 8790Sstevel@tonic-gate *msiq_tail); 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate return (DDI_SUCCESS); 8820Sstevel@tonic-gate } 8830Sstevel@tonic-gate 8840Sstevel@tonic-gate /*ARGSUSED*/ 8850Sstevel@tonic-gate void 8860Sstevel@tonic-gate px_lib_get_msiq_rec(dev_info_t *dip, px_msiq_t *msiq_p, msiq_rec_t *msiq_rec_p) 8870Sstevel@tonic-gate { 8880Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 8890Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 8900Sstevel@tonic-gate eq_rec_t *eq_rec_p = (eq_rec_t *)msiq_p->msiq_curr; 8910Sstevel@tonic-gate 8920Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: dip 0x%p eq_rec_p 0x%p\n", 8930Sstevel@tonic-gate dip, eq_rec_p); 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate if (!eq_rec_p->eq_rec_rid) { 8960Sstevel@tonic-gate /* Set msiq_rec_rid to zero */ 8970Sstevel@tonic-gate msiq_rec_p->msiq_rec_rid = 0; 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate return; 9000Sstevel@tonic-gate } 9010Sstevel@tonic-gate 9020Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: EQ RECORD, " 9030Sstevel@tonic-gate "eq_rec_rid 0x%llx eq_rec_fmt_type 0x%llx " 9040Sstevel@tonic-gate "eq_rec_len 0x%llx eq_rec_addr0 0x%llx " 9050Sstevel@tonic-gate "eq_rec_addr1 0x%llx eq_rec_data0 0x%llx " 9060Sstevel@tonic-gate "eq_rec_data1 0x%llx\n", eq_rec_p->eq_rec_rid, 9070Sstevel@tonic-gate eq_rec_p->eq_rec_fmt_type, eq_rec_p->eq_rec_len, 9080Sstevel@tonic-gate eq_rec_p->eq_rec_addr0, eq_rec_p->eq_rec_addr1, 9090Sstevel@tonic-gate eq_rec_p->eq_rec_data0, eq_rec_p->eq_rec_data1); 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate /* 9120Sstevel@tonic-gate * Only upper 4 bits of eq_rec_fmt_type is used 9130Sstevel@tonic-gate * to identify the EQ record type. 9140Sstevel@tonic-gate */ 9150Sstevel@tonic-gate switch (eq_rec_p->eq_rec_fmt_type >> 3) { 9160Sstevel@tonic-gate case EQ_REC_MSI32: 9170Sstevel@tonic-gate msiq_rec_p->msiq_rec_type = MSI32_REC; 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate if (pxu_p->chip_id == FIRE_VER_10) { 9200Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msi.msi_data = 9210Sstevel@tonic-gate (eq_rec_p->eq_rec_data0 & 0xFF) << 8 | 9220Sstevel@tonic-gate (eq_rec_p->eq_rec_data0 & 0xFF00) >> 8; 9230Sstevel@tonic-gate } else { 9240Sstevel@tonic-gate /* Default case is FIRE2.0 */ 9250Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msi.msi_data = 9260Sstevel@tonic-gate eq_rec_p->eq_rec_data0; 9270Sstevel@tonic-gate } 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate break; 9300Sstevel@tonic-gate case EQ_REC_MSI64: 9310Sstevel@tonic-gate msiq_rec_p->msiq_rec_type = MSI64_REC; 9320Sstevel@tonic-gate 9330Sstevel@tonic-gate if (pxu_p->chip_id == FIRE_VER_10) { 9340Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msi.msi_data = 9350Sstevel@tonic-gate (eq_rec_p->eq_rec_data0 & 0xFF) << 8 | 9360Sstevel@tonic-gate (eq_rec_p->eq_rec_data0 & 0xFF00) >> 8; 9370Sstevel@tonic-gate } else { 9380Sstevel@tonic-gate /* Default case is FIRE2.0 */ 9390Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msi.msi_data = 9400Sstevel@tonic-gate eq_rec_p->eq_rec_data0; 9410Sstevel@tonic-gate } 9420Sstevel@tonic-gate 9430Sstevel@tonic-gate break; 9440Sstevel@tonic-gate case EQ_REC_MSG: 9450Sstevel@tonic-gate msiq_rec_p->msiq_rec_type = MSG_REC; 9460Sstevel@tonic-gate 9470Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msg.msg_route = 9480Sstevel@tonic-gate eq_rec_p->eq_rec_fmt_type & 7; 9490Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msg.msg_targ = eq_rec_p->eq_rec_rid; 9500Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msg.msg_code = eq_rec_p->eq_rec_data0; 9510Sstevel@tonic-gate break; 9520Sstevel@tonic-gate default: 9530Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: px_lib_get_msiq_rec: " 9540Sstevel@tonic-gate "0x%lx is an unknown EQ record type", 9550Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip), 9560Sstevel@tonic-gate eq_rec_p->eq_rec_fmt_type); 9570Sstevel@tonic-gate break; 9580Sstevel@tonic-gate } 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate msiq_rec_p->msiq_rec_rid = eq_rec_p->eq_rec_rid; 9610Sstevel@tonic-gate msiq_rec_p->msiq_rec_msi_addr = ((eq_rec_p->eq_rec_addr1 << 16) | 9620Sstevel@tonic-gate (eq_rec_p->eq_rec_addr0 << 2)); 9630Sstevel@tonic-gate 9640Sstevel@tonic-gate /* Zero out eq_rec_rid field */ 9650Sstevel@tonic-gate eq_rec_p->eq_rec_rid = 0; 9660Sstevel@tonic-gate } 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate /* 9690Sstevel@tonic-gate * MSI Functions: 9700Sstevel@tonic-gate */ 9710Sstevel@tonic-gate /*ARGSUSED*/ 9720Sstevel@tonic-gate int 9730Sstevel@tonic-gate px_lib_msi_init(dev_info_t *dip) 9740Sstevel@tonic-gate { 9750Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 9760Sstevel@tonic-gate px_msi_state_t *msi_state_p = &px_p->px_ib_p->ib_msi_state; 9770Sstevel@tonic-gate uint64_t ret; 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_init: dip 0x%p\n", dip); 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate if ((ret = hvio_msi_init(DIP_TO_HANDLE(dip), 9820Sstevel@tonic-gate msi_state_p->msi_addr32, msi_state_p->msi_addr64)) != H_EOK) { 9830Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msi_init failed, ret 0x%lx\n", 9840Sstevel@tonic-gate ret); 9850Sstevel@tonic-gate return (DDI_FAILURE); 9860Sstevel@tonic-gate } 9870Sstevel@tonic-gate 9880Sstevel@tonic-gate return (DDI_SUCCESS); 9890Sstevel@tonic-gate } 9900Sstevel@tonic-gate 9910Sstevel@tonic-gate /*ARGSUSED*/ 9920Sstevel@tonic-gate int 9930Sstevel@tonic-gate px_lib_msi_getmsiq(dev_info_t *dip, msinum_t msi_num, 9940Sstevel@tonic-gate msiqid_t *msiq_id) 9950Sstevel@tonic-gate { 9960Sstevel@tonic-gate uint64_t ret; 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: dip 0x%p msi_num 0x%x\n", 9990Sstevel@tonic-gate dip, msi_num); 10000Sstevel@tonic-gate 10010Sstevel@tonic-gate if ((ret = hvio_msi_getmsiq(DIP_TO_HANDLE(dip), 10020Sstevel@tonic-gate msi_num, msiq_id)) != H_EOK) { 10030Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, 10040Sstevel@tonic-gate "hvio_msi_getmsiq failed, ret 0x%lx\n", ret); 10050Sstevel@tonic-gate return (DDI_FAILURE); 10060Sstevel@tonic-gate } 10070Sstevel@tonic-gate 10080Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: msiq_id 0x%x\n", 10090Sstevel@tonic-gate *msiq_id); 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate return (DDI_SUCCESS); 10120Sstevel@tonic-gate } 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate /*ARGSUSED*/ 10150Sstevel@tonic-gate int 10160Sstevel@tonic-gate px_lib_msi_setmsiq(dev_info_t *dip, msinum_t msi_num, 10170Sstevel@tonic-gate msiqid_t msiq_id, msi_type_t msitype) 10180Sstevel@tonic-gate { 10190Sstevel@tonic-gate uint64_t ret; 10200Sstevel@tonic-gate 10210Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setmsiq: dip 0x%p msi_num 0x%x " 10220Sstevel@tonic-gate "msq_id 0x%x\n", dip, msi_num, msiq_id); 10230Sstevel@tonic-gate 10240Sstevel@tonic-gate if ((ret = hvio_msi_setmsiq(DIP_TO_HANDLE(dip), 10250Sstevel@tonic-gate msi_num, msiq_id)) != H_EOK) { 10260Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, 10270Sstevel@tonic-gate "hvio_msi_setmsiq failed, ret 0x%lx\n", ret); 10280Sstevel@tonic-gate return (DDI_FAILURE); 10290Sstevel@tonic-gate } 10300Sstevel@tonic-gate 10310Sstevel@tonic-gate return (DDI_SUCCESS); 10320Sstevel@tonic-gate } 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate /*ARGSUSED*/ 10350Sstevel@tonic-gate int 10360Sstevel@tonic-gate px_lib_msi_getvalid(dev_info_t *dip, msinum_t msi_num, 10370Sstevel@tonic-gate pci_msi_valid_state_t *msi_valid_state) 10380Sstevel@tonic-gate { 10390Sstevel@tonic-gate uint64_t ret; 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: dip 0x%p msi_num 0x%x\n", 10420Sstevel@tonic-gate dip, msi_num); 10430Sstevel@tonic-gate 10440Sstevel@tonic-gate if ((ret = hvio_msi_getvalid(DIP_TO_HANDLE(dip), 10450Sstevel@tonic-gate msi_num, msi_valid_state)) != H_EOK) { 10460Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, 10470Sstevel@tonic-gate "hvio_msi_getvalid failed, ret 0x%lx\n", ret); 10480Sstevel@tonic-gate return (DDI_FAILURE); 10490Sstevel@tonic-gate } 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: msiq_id 0x%x\n", 10520Sstevel@tonic-gate *msi_valid_state); 10530Sstevel@tonic-gate 10540Sstevel@tonic-gate return (DDI_SUCCESS); 10550Sstevel@tonic-gate } 10560Sstevel@tonic-gate 10570Sstevel@tonic-gate /*ARGSUSED*/ 10580Sstevel@tonic-gate int 10590Sstevel@tonic-gate px_lib_msi_setvalid(dev_info_t *dip, msinum_t msi_num, 10600Sstevel@tonic-gate pci_msi_valid_state_t msi_valid_state) 10610Sstevel@tonic-gate { 10620Sstevel@tonic-gate uint64_t ret; 10630Sstevel@tonic-gate 10640Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setvalid: dip 0x%p msi_num 0x%x " 10650Sstevel@tonic-gate "msi_valid_state 0x%x\n", dip, msi_num, msi_valid_state); 10660Sstevel@tonic-gate 10670Sstevel@tonic-gate if ((ret = hvio_msi_setvalid(DIP_TO_HANDLE(dip), 10680Sstevel@tonic-gate msi_num, msi_valid_state)) != H_EOK) { 10690Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, 10700Sstevel@tonic-gate "hvio_msi_setvalid failed, ret 0x%lx\n", ret); 10710Sstevel@tonic-gate return (DDI_FAILURE); 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate return (DDI_SUCCESS); 10750Sstevel@tonic-gate } 10760Sstevel@tonic-gate 10770Sstevel@tonic-gate /*ARGSUSED*/ 10780Sstevel@tonic-gate int 10790Sstevel@tonic-gate px_lib_msi_getstate(dev_info_t *dip, msinum_t msi_num, 10800Sstevel@tonic-gate pci_msi_state_t *msi_state) 10810Sstevel@tonic-gate { 10820Sstevel@tonic-gate uint64_t ret; 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: dip 0x%p msi_num 0x%x\n", 10850Sstevel@tonic-gate dip, msi_num); 10860Sstevel@tonic-gate 10870Sstevel@tonic-gate if ((ret = hvio_msi_getstate(DIP_TO_HANDLE(dip), 10880Sstevel@tonic-gate msi_num, msi_state)) != H_EOK) { 10890Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, 10900Sstevel@tonic-gate "hvio_msi_getstate failed, ret 0x%lx\n", ret); 10910Sstevel@tonic-gate return (DDI_FAILURE); 10920Sstevel@tonic-gate } 10930Sstevel@tonic-gate 10940Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: msi_state 0x%x\n", 10950Sstevel@tonic-gate *msi_state); 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate return (DDI_SUCCESS); 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate /*ARGSUSED*/ 11010Sstevel@tonic-gate int 11020Sstevel@tonic-gate px_lib_msi_setstate(dev_info_t *dip, msinum_t msi_num, 11030Sstevel@tonic-gate pci_msi_state_t msi_state) 11040Sstevel@tonic-gate { 11050Sstevel@tonic-gate uint64_t ret; 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setstate: dip 0x%p msi_num 0x%x " 11080Sstevel@tonic-gate "msi_state 0x%x\n", dip, msi_num, msi_state); 11090Sstevel@tonic-gate 11100Sstevel@tonic-gate if ((ret = hvio_msi_setstate(DIP_TO_HANDLE(dip), 11110Sstevel@tonic-gate msi_num, msi_state)) != H_EOK) { 11120Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, 11130Sstevel@tonic-gate "hvio_msi_setstate failed, ret 0x%lx\n", ret); 11140Sstevel@tonic-gate return (DDI_FAILURE); 11150Sstevel@tonic-gate } 11160Sstevel@tonic-gate 11170Sstevel@tonic-gate return (DDI_SUCCESS); 11180Sstevel@tonic-gate } 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate /* 11210Sstevel@tonic-gate * MSG Functions: 11220Sstevel@tonic-gate */ 11230Sstevel@tonic-gate /*ARGSUSED*/ 11240Sstevel@tonic-gate int 11250Sstevel@tonic-gate px_lib_msg_getmsiq(dev_info_t *dip, pcie_msg_type_t msg_type, 11260Sstevel@tonic-gate msiqid_t *msiq_id) 11270Sstevel@tonic-gate { 11280Sstevel@tonic-gate uint64_t ret; 11290Sstevel@tonic-gate 11300Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_getmsiq: dip 0x%p msg_type 0x%x\n", 11310Sstevel@tonic-gate dip, msg_type); 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate if ((ret = hvio_msg_getmsiq(DIP_TO_HANDLE(dip), 11340Sstevel@tonic-gate msg_type, msiq_id)) != H_EOK) { 11350Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, 11360Sstevel@tonic-gate "hvio_msg_getmsiq failed, ret 0x%lx\n", ret); 11370Sstevel@tonic-gate return (DDI_FAILURE); 11380Sstevel@tonic-gate } 11390Sstevel@tonic-gate 11400Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msg_getmsiq: msiq_id 0x%x\n", 11410Sstevel@tonic-gate *msiq_id); 11420Sstevel@tonic-gate 11430Sstevel@tonic-gate return (DDI_SUCCESS); 11440Sstevel@tonic-gate } 11450Sstevel@tonic-gate 11460Sstevel@tonic-gate /*ARGSUSED*/ 11470Sstevel@tonic-gate int 11480Sstevel@tonic-gate px_lib_msg_setmsiq(dev_info_t *dip, pcie_msg_type_t msg_type, 11490Sstevel@tonic-gate msiqid_t msiq_id) 11500Sstevel@tonic-gate { 11510Sstevel@tonic-gate uint64_t ret; 11520Sstevel@tonic-gate 11530Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msi_setstate: dip 0x%p msg_type 0x%x " 11540Sstevel@tonic-gate "msiq_id 0x%x\n", dip, msg_type, msiq_id); 11550Sstevel@tonic-gate 11560Sstevel@tonic-gate if ((ret = hvio_msg_setmsiq(DIP_TO_HANDLE(dip), 11570Sstevel@tonic-gate msg_type, msiq_id)) != H_EOK) { 11580Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, 11590Sstevel@tonic-gate "hvio_msg_setmsiq failed, ret 0x%lx\n", ret); 11600Sstevel@tonic-gate return (DDI_FAILURE); 11610Sstevel@tonic-gate } 11620Sstevel@tonic-gate 11630Sstevel@tonic-gate return (DDI_SUCCESS); 11640Sstevel@tonic-gate } 11650Sstevel@tonic-gate 11660Sstevel@tonic-gate /*ARGSUSED*/ 11670Sstevel@tonic-gate int 11680Sstevel@tonic-gate px_lib_msg_getvalid(dev_info_t *dip, pcie_msg_type_t msg_type, 11690Sstevel@tonic-gate pcie_msg_valid_state_t *msg_valid_state) 11700Sstevel@tonic-gate { 11710Sstevel@tonic-gate uint64_t ret; 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_getvalid: dip 0x%p msg_type 0x%x\n", 11740Sstevel@tonic-gate dip, msg_type); 11750Sstevel@tonic-gate 11760Sstevel@tonic-gate if ((ret = hvio_msg_getvalid(DIP_TO_HANDLE(dip), msg_type, 11770Sstevel@tonic-gate msg_valid_state)) != H_EOK) { 11780Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, 11790Sstevel@tonic-gate "hvio_msg_getvalid failed, ret 0x%lx\n", ret); 11800Sstevel@tonic-gate return (DDI_FAILURE); 11810Sstevel@tonic-gate } 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msg_getvalid: msg_valid_state 0x%x\n", 11840Sstevel@tonic-gate *msg_valid_state); 11850Sstevel@tonic-gate 11860Sstevel@tonic-gate return (DDI_SUCCESS); 11870Sstevel@tonic-gate } 11880Sstevel@tonic-gate 11890Sstevel@tonic-gate /*ARGSUSED*/ 11900Sstevel@tonic-gate int 11910Sstevel@tonic-gate px_lib_msg_setvalid(dev_info_t *dip, pcie_msg_type_t msg_type, 11920Sstevel@tonic-gate pcie_msg_valid_state_t msg_valid_state) 11930Sstevel@tonic-gate { 11940Sstevel@tonic-gate uint64_t ret; 11950Sstevel@tonic-gate 11960Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_setvalid: dip 0x%p msg_type 0x%x " 11970Sstevel@tonic-gate "msg_valid_state 0x%x\n", dip, msg_type, msg_valid_state); 11980Sstevel@tonic-gate 11990Sstevel@tonic-gate if ((ret = hvio_msg_setvalid(DIP_TO_HANDLE(dip), msg_type, 12000Sstevel@tonic-gate msg_valid_state)) != H_EOK) { 12010Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, 12020Sstevel@tonic-gate "hvio_msg_setvalid failed, ret 0x%lx\n", ret); 12030Sstevel@tonic-gate return (DDI_FAILURE); 12040Sstevel@tonic-gate } 12050Sstevel@tonic-gate 12060Sstevel@tonic-gate return (DDI_SUCCESS); 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate 12090Sstevel@tonic-gate /* 12100Sstevel@tonic-gate * Suspend/Resume Functions: 12110Sstevel@tonic-gate * Currently unsupported by hypervisor 12120Sstevel@tonic-gate */ 12130Sstevel@tonic-gate int 12140Sstevel@tonic-gate px_lib_suspend(dev_info_t *dip) 12150Sstevel@tonic-gate { 12160Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 12170Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 12180Sstevel@tonic-gate devhandle_t dev_hdl, xbus_dev_hdl; 12190Sstevel@tonic-gate uint64_t ret; 12200Sstevel@tonic-gate 12210Sstevel@tonic-gate DBG(DBG_DETACH, dip, "px_lib_suspend: dip 0x%p\n", dip); 12220Sstevel@tonic-gate 1223*27Sjchu dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_CSR]; 1224*27Sjchu xbus_dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_XBC]; 12250Sstevel@tonic-gate 12260Sstevel@tonic-gate if ((ret = hvio_suspend(dev_hdl, pxu_p)) == H_EOK) { 12270Sstevel@tonic-gate px_p->px_cb_p->xbc_attachcnt--; 12280Sstevel@tonic-gate if (px_p->px_cb_p->xbc_attachcnt == 0) 12290Sstevel@tonic-gate if ((ret = hvio_cb_suspend(xbus_dev_hdl, pxu_p)) 12300Sstevel@tonic-gate != H_EOK) 12310Sstevel@tonic-gate px_p->px_cb_p->xbc_attachcnt++; 12320Sstevel@tonic-gate } 12330Sstevel@tonic-gate 12340Sstevel@tonic-gate return ((ret != H_EOK) ? DDI_FAILURE: DDI_SUCCESS); 12350Sstevel@tonic-gate } 12360Sstevel@tonic-gate 12370Sstevel@tonic-gate void 12380Sstevel@tonic-gate px_lib_resume(dev_info_t *dip) 12390Sstevel@tonic-gate { 12400Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 12410Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 12420Sstevel@tonic-gate devhandle_t dev_hdl, xbus_dev_hdl; 12430Sstevel@tonic-gate devino_t pec_ino = px_p->px_inos[PX_INTR_PEC]; 12440Sstevel@tonic-gate devino_t xbc_ino = px_p->px_inos[PX_INTR_XBC]; 12450Sstevel@tonic-gate 12460Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_resume: dip 0x%p\n", dip); 12470Sstevel@tonic-gate 1248*27Sjchu dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_CSR]; 1249*27Sjchu xbus_dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_XBC]; 12500Sstevel@tonic-gate 12510Sstevel@tonic-gate px_p->px_cb_p->xbc_attachcnt++; 12520Sstevel@tonic-gate if (px_p->px_cb_p->xbc_attachcnt == 1) 12530Sstevel@tonic-gate hvio_cb_resume(dev_hdl, xbus_dev_hdl, xbc_ino, pxu_p); 12540Sstevel@tonic-gate hvio_resume(dev_hdl, pec_ino, pxu_p); 12550Sstevel@tonic-gate } 12560Sstevel@tonic-gate 12570Sstevel@tonic-gate /* 12580Sstevel@tonic-gate * PCI tool Functions: 12590Sstevel@tonic-gate * Currently unsupported by hypervisor 12600Sstevel@tonic-gate */ 12610Sstevel@tonic-gate /*ARGSUSED*/ 12620Sstevel@tonic-gate int 12630Sstevel@tonic-gate px_lib_tools_dev_reg_ops(dev_info_t *dip, void *arg, int cmd, int mode) 12640Sstevel@tonic-gate { 12650Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 12660Sstevel@tonic-gate 12670Sstevel@tonic-gate DBG(DBG_TOOLS, dip, "px_lib_tools_dev_reg_ops: dip 0x%p arg 0x%p " 12680Sstevel@tonic-gate "cmd 0x%x mode 0x%x\n", dip, arg, cmd, mode); 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate return (px_dev_reg_ops(dip, arg, cmd, mode, px_p)); 12710Sstevel@tonic-gate } 12720Sstevel@tonic-gate 12730Sstevel@tonic-gate /*ARGSUSED*/ 12740Sstevel@tonic-gate int 12750Sstevel@tonic-gate px_lib_tools_bus_reg_ops(dev_info_t *dip, void *arg, int cmd, int mode) 12760Sstevel@tonic-gate { 12770Sstevel@tonic-gate DBG(DBG_TOOLS, dip, "px_lib_tools_bus_reg_ops: dip 0x%p arg 0x%p " 12780Sstevel@tonic-gate "cmd 0x%x mode 0x%x\n", dip, arg, cmd, mode); 12790Sstevel@tonic-gate 12800Sstevel@tonic-gate return (px_bus_reg_ops(dip, arg, cmd, mode)); 12810Sstevel@tonic-gate } 12820Sstevel@tonic-gate 12830Sstevel@tonic-gate /*ARGSUSED*/ 12840Sstevel@tonic-gate int 12850Sstevel@tonic-gate px_lib_tools_intr_admn(dev_info_t *dip, void *arg, int cmd, int mode) 12860Sstevel@tonic-gate { 12870Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 12880Sstevel@tonic-gate 12890Sstevel@tonic-gate DBG(DBG_TOOLS, dip, "px_lib_tools_intr_admn: dip 0x%p arg 0x%p " 12900Sstevel@tonic-gate "cmd 0x%x mode 0x%x\n", dip, arg, cmd, mode); 12910Sstevel@tonic-gate 12920Sstevel@tonic-gate return (px_intr_admn(dip, arg, cmd, mode, px_p)); 12930Sstevel@tonic-gate } 12940Sstevel@tonic-gate 12950Sstevel@tonic-gate /* 12960Sstevel@tonic-gate * Misc Functions: 12970Sstevel@tonic-gate * Currently unsupported by hypervisor 12980Sstevel@tonic-gate */ 12990Sstevel@tonic-gate uint64_t 1300*27Sjchu px_lib_get_cb(dev_info_t *dip) 13010Sstevel@tonic-gate { 1302*27Sjchu px_t *px_p = DIP_TO_STATE(dip); 1303*27Sjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 1304*27Sjchu 1305*27Sjchu return (CSR_XR((caddr_t)pxu_p->px_address[PX_REG_XBC], JBUS_SCRATCH_1)); 13060Sstevel@tonic-gate } 13070Sstevel@tonic-gate 13080Sstevel@tonic-gate void 1309*27Sjchu px_lib_set_cb(dev_info_t *dip, uint64_t val) 13100Sstevel@tonic-gate { 1311*27Sjchu px_t *px_p = DIP_TO_STATE(dip); 1312*27Sjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 1313*27Sjchu 1314*27Sjchu CSR_XS((caddr_t)pxu_p->px_address[PX_REG_XBC], JBUS_SCRATCH_1, val); 13150Sstevel@tonic-gate } 13160Sstevel@tonic-gate 13170Sstevel@tonic-gate /*ARGSUSED*/ 13180Sstevel@tonic-gate int 13190Sstevel@tonic-gate px_lib_map_vconfig(dev_info_t *dip, 13200Sstevel@tonic-gate ddi_map_req_t *mp, pci_config_offset_t off, 13210Sstevel@tonic-gate pci_regspec_t *rp, caddr_t *addrp) 13220Sstevel@tonic-gate { 13230Sstevel@tonic-gate /* 13240Sstevel@tonic-gate * No special config space access services in this layer. 13250Sstevel@tonic-gate */ 13260Sstevel@tonic-gate return (DDI_FAILURE); 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 1329*27Sjchu static void 1330*27Sjchu px_lib_clr_errs(px_t *px_p, px_pec_t *pec_p) 1331*27Sjchu { 1332*27Sjchu dev_info_t *rpdip = px_p->px_dip; 1333*27Sjchu px_cb_t *cb_p = px_p->px_cb_p; 1334*27Sjchu int err = PX_OK, ret; 1335*27Sjchu int acctype = pec_p->pec_safeacc_type; 1336*27Sjchu ddi_fm_error_t derr; 1337*27Sjchu 1338*27Sjchu /* Create the derr */ 1339*27Sjchu bzero(&derr, sizeof (ddi_fm_error_t)); 1340*27Sjchu derr.fme_version = DDI_FME_VERSION; 1341*27Sjchu derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1); 1342*27Sjchu derr.fme_flag = acctype; 1343*27Sjchu 1344*27Sjchu if (acctype == DDI_FM_ERR_EXPECTED) { 1345*27Sjchu derr.fme_status = DDI_FM_NONFATAL; 1346*27Sjchu ndi_fm_acc_err_set(pec_p->pec_acc_hdl, &derr); 1347*27Sjchu } 1348*27Sjchu 1349*27Sjchu mutex_enter(&cb_p->xbc_fm_mutex); 1350*27Sjchu 1351*27Sjchu /* send ereport/handle/clear fire registers */ 1352*27Sjchu err = px_err_handle(px_p, &derr, PX_LIB_CALL, B_TRUE); 1353*27Sjchu 1354*27Sjchu /* Check all child devices for errors */ 1355*27Sjchu ret = ndi_fm_handler_dispatch(rpdip, NULL, &derr); 1356*27Sjchu 1357*27Sjchu mutex_exit(&cb_p->xbc_fm_mutex); 1358*27Sjchu 1359*27Sjchu /* 1360*27Sjchu * PX_FATAL_HW indicates a condition recovered from Fatal-Reset, 1361*27Sjchu * therefore it does not cause panic. 1362*27Sjchu */ 1363*27Sjchu if ((err & (PX_FATAL_GOS | PX_FATAL_SW)) || (ret == DDI_FM_FATAL)) 1364*27Sjchu fm_panic("Fatal System Port Error has occurred\n"); 1365*27Sjchu } 1366*27Sjchu 13670Sstevel@tonic-gate #ifdef DEBUG 13680Sstevel@tonic-gate int px_peekfault_cnt = 0; 13690Sstevel@tonic-gate int px_pokefault_cnt = 0; 13700Sstevel@tonic-gate #endif /* DEBUG */ 13710Sstevel@tonic-gate 13720Sstevel@tonic-gate /*ARGSUSED*/ 13730Sstevel@tonic-gate static int 13740Sstevel@tonic-gate px_lib_do_poke(dev_info_t *dip, dev_info_t *rdip, 13750Sstevel@tonic-gate peekpoke_ctlops_t *in_args) 13760Sstevel@tonic-gate { 13770Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 13780Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p; 13790Sstevel@tonic-gate int err = DDI_SUCCESS; 13800Sstevel@tonic-gate on_trap_data_t otd; 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate mutex_enter(&pec_p->pec_pokefault_mutex); 13830Sstevel@tonic-gate pec_p->pec_ontrap_data = &otd; 1384*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_POKE; 13850Sstevel@tonic-gate 13860Sstevel@tonic-gate /* Set up protected environment. */ 13870Sstevel@tonic-gate if (!on_trap(&otd, OT_DATA_ACCESS)) { 13880Sstevel@tonic-gate uintptr_t tramp = otd.ot_trampoline; 13890Sstevel@tonic-gate 13900Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&poke_fault; 13910Sstevel@tonic-gate err = do_poke(in_args->size, (void *)in_args->dev_addr, 13920Sstevel@tonic-gate (void *)in_args->host_addr); 13930Sstevel@tonic-gate otd.ot_trampoline = tramp; 13940Sstevel@tonic-gate } else 13950Sstevel@tonic-gate err = DDI_FAILURE; 13960Sstevel@tonic-gate 1397*27Sjchu px_lib_clr_errs(px_p, pec_p); 1398*27Sjchu 13990Sstevel@tonic-gate if (otd.ot_trap & OT_DATA_ACCESS) 14000Sstevel@tonic-gate err = DDI_FAILURE; 14010Sstevel@tonic-gate 14020Sstevel@tonic-gate /* Take down protected environment. */ 14030Sstevel@tonic-gate no_trap(); 14040Sstevel@tonic-gate 14050Sstevel@tonic-gate pec_p->pec_ontrap_data = NULL; 1406*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED; 14070Sstevel@tonic-gate mutex_exit(&pec_p->pec_pokefault_mutex); 14080Sstevel@tonic-gate 14090Sstevel@tonic-gate #ifdef DEBUG 14100Sstevel@tonic-gate if (err == DDI_FAILURE) 14110Sstevel@tonic-gate px_pokefault_cnt++; 14120Sstevel@tonic-gate #endif 14130Sstevel@tonic-gate return (err); 14140Sstevel@tonic-gate } 14150Sstevel@tonic-gate 14160Sstevel@tonic-gate /*ARGSUSED*/ 14170Sstevel@tonic-gate static int 14180Sstevel@tonic-gate px_lib_do_caut_put(dev_info_t *dip, dev_info_t *rdip, 14190Sstevel@tonic-gate peekpoke_ctlops_t *cautacc_ctlops_arg) 14200Sstevel@tonic-gate { 14210Sstevel@tonic-gate size_t size = cautacc_ctlops_arg->size; 14220Sstevel@tonic-gate uintptr_t dev_addr = cautacc_ctlops_arg->dev_addr; 14230Sstevel@tonic-gate uintptr_t host_addr = cautacc_ctlops_arg->host_addr; 14240Sstevel@tonic-gate ddi_acc_impl_t *hp = (ddi_acc_impl_t *)cautacc_ctlops_arg->handle; 14250Sstevel@tonic-gate size_t repcount = cautacc_ctlops_arg->repcount; 14260Sstevel@tonic-gate uint_t flags = cautacc_ctlops_arg->flags; 14270Sstevel@tonic-gate 14280Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 14290Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p; 14300Sstevel@tonic-gate int err = DDI_SUCCESS; 14310Sstevel@tonic-gate 1432*27Sjchu /* 1433*27Sjchu * Note that i_ndi_busop_access_enter ends up grabbing the pokefault 1434*27Sjchu * mutex. 1435*27Sjchu */ 14360Sstevel@tonic-gate i_ndi_busop_access_enter(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 14370Sstevel@tonic-gate 1438*27Sjchu pec_p->pec_ontrap_data = (on_trap_data_t *)hp->ahi_err->err_ontrap; 1439*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED; 1440*27Sjchu hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED; 14410Sstevel@tonic-gate 14420Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) { 14430Sstevel@tonic-gate for (; repcount; repcount--) { 14440Sstevel@tonic-gate switch (size) { 14450Sstevel@tonic-gate 14460Sstevel@tonic-gate case sizeof (uint8_t): 14470Sstevel@tonic-gate i_ddi_put8(hp, (uint8_t *)dev_addr, 14480Sstevel@tonic-gate *(uint8_t *)host_addr); 14490Sstevel@tonic-gate break; 14500Sstevel@tonic-gate 14510Sstevel@tonic-gate case sizeof (uint16_t): 14520Sstevel@tonic-gate i_ddi_put16(hp, (uint16_t *)dev_addr, 14530Sstevel@tonic-gate *(uint16_t *)host_addr); 14540Sstevel@tonic-gate break; 14550Sstevel@tonic-gate 14560Sstevel@tonic-gate case sizeof (uint32_t): 14570Sstevel@tonic-gate i_ddi_put32(hp, (uint32_t *)dev_addr, 14580Sstevel@tonic-gate *(uint32_t *)host_addr); 14590Sstevel@tonic-gate break; 14600Sstevel@tonic-gate 14610Sstevel@tonic-gate case sizeof (uint64_t): 14620Sstevel@tonic-gate i_ddi_put64(hp, (uint64_t *)dev_addr, 14630Sstevel@tonic-gate *(uint64_t *)host_addr); 14640Sstevel@tonic-gate break; 14650Sstevel@tonic-gate } 14660Sstevel@tonic-gate 14670Sstevel@tonic-gate host_addr += size; 14680Sstevel@tonic-gate 14690Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR) 14700Sstevel@tonic-gate dev_addr += size; 14710Sstevel@tonic-gate 1472*27Sjchu px_lib_clr_errs(px_p, pec_p); 1473*27Sjchu 14740Sstevel@tonic-gate if (pec_p->pec_ontrap_data->ot_trap & OT_DATA_ACCESS) { 14750Sstevel@tonic-gate err = DDI_FAILURE; 14760Sstevel@tonic-gate #ifdef DEBUG 14770Sstevel@tonic-gate px_pokefault_cnt++; 14780Sstevel@tonic-gate #endif 14790Sstevel@tonic-gate break; 14800Sstevel@tonic-gate } 14810Sstevel@tonic-gate } 14820Sstevel@tonic-gate } 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate i_ddi_notrap((ddi_acc_handle_t)hp); 14850Sstevel@tonic-gate pec_p->pec_ontrap_data = NULL; 1486*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED; 14870Sstevel@tonic-gate i_ndi_busop_access_exit(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 14880Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_UNEXPECTED; 14890Sstevel@tonic-gate 14900Sstevel@tonic-gate return (err); 14910Sstevel@tonic-gate } 14920Sstevel@tonic-gate 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate int 14950Sstevel@tonic-gate px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip, 14960Sstevel@tonic-gate peekpoke_ctlops_t *in_args) 14970Sstevel@tonic-gate { 14980Sstevel@tonic-gate return (in_args->handle ? px_lib_do_caut_put(dip, rdip, in_args) : 14990Sstevel@tonic-gate px_lib_do_poke(dip, rdip, in_args)); 15000Sstevel@tonic-gate } 15010Sstevel@tonic-gate 15020Sstevel@tonic-gate 15030Sstevel@tonic-gate /*ARGSUSED*/ 15040Sstevel@tonic-gate static int 15050Sstevel@tonic-gate px_lib_do_peek(dev_info_t *dip, peekpoke_ctlops_t *in_args) 15060Sstevel@tonic-gate { 1507*27Sjchu px_t *px_p = DIP_TO_STATE(dip); 1508*27Sjchu px_pec_t *pec_p = px_p->px_pec_p; 15090Sstevel@tonic-gate int err = DDI_SUCCESS; 15100Sstevel@tonic-gate on_trap_data_t otd; 15110Sstevel@tonic-gate 1512*27Sjchu mutex_enter(&pec_p->pec_pokefault_mutex); 1513*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_PEEK; 1514*27Sjchu 15150Sstevel@tonic-gate if (!on_trap(&otd, OT_DATA_ACCESS)) { 15160Sstevel@tonic-gate uintptr_t tramp = otd.ot_trampoline; 15170Sstevel@tonic-gate 15180Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&peek_fault; 15190Sstevel@tonic-gate err = do_peek(in_args->size, (void *)in_args->dev_addr, 15200Sstevel@tonic-gate (void *)in_args->host_addr); 15210Sstevel@tonic-gate otd.ot_trampoline = tramp; 15220Sstevel@tonic-gate } else 15230Sstevel@tonic-gate err = DDI_FAILURE; 15240Sstevel@tonic-gate 15250Sstevel@tonic-gate no_trap(); 1526*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED; 1527*27Sjchu mutex_exit(&pec_p->pec_pokefault_mutex); 15280Sstevel@tonic-gate 15290Sstevel@tonic-gate #ifdef DEBUG 15300Sstevel@tonic-gate if (err == DDI_FAILURE) 15310Sstevel@tonic-gate px_peekfault_cnt++; 15320Sstevel@tonic-gate #endif 15330Sstevel@tonic-gate return (err); 15340Sstevel@tonic-gate } 15350Sstevel@tonic-gate 15360Sstevel@tonic-gate 15370Sstevel@tonic-gate static int 15380Sstevel@tonic-gate px_lib_do_caut_get(dev_info_t *dip, peekpoke_ctlops_t *cautacc_ctlops_arg) 15390Sstevel@tonic-gate { 15400Sstevel@tonic-gate size_t size = cautacc_ctlops_arg->size; 15410Sstevel@tonic-gate uintptr_t dev_addr = cautacc_ctlops_arg->dev_addr; 15420Sstevel@tonic-gate uintptr_t host_addr = cautacc_ctlops_arg->host_addr; 15430Sstevel@tonic-gate ddi_acc_impl_t *hp = (ddi_acc_impl_t *)cautacc_ctlops_arg->handle; 15440Sstevel@tonic-gate size_t repcount = cautacc_ctlops_arg->repcount; 15450Sstevel@tonic-gate uint_t flags = cautacc_ctlops_arg->flags; 15460Sstevel@tonic-gate 15470Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip); 15480Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p; 15490Sstevel@tonic-gate int err = DDI_SUCCESS; 15500Sstevel@tonic-gate 1551*27Sjchu /* 1552*27Sjchu * Note that i_ndi_busop_access_enter ends up grabbing the pokefault 1553*27Sjchu * mutex. 1554*27Sjchu */ 1555*27Sjchu i_ndi_busop_access_enter(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 1556*27Sjchu 1557*27Sjchu pec_p->pec_ontrap_data = (on_trap_data_t *)hp->ahi_err->err_ontrap; 1558*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED; 15590Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED; 15600Sstevel@tonic-gate 15610Sstevel@tonic-gate if (repcount == 1) { 15620Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) { 15630Sstevel@tonic-gate i_ddi_caut_get(size, (void *)dev_addr, 15640Sstevel@tonic-gate (void *)host_addr); 15650Sstevel@tonic-gate } else { 15660Sstevel@tonic-gate int i; 15670Sstevel@tonic-gate uint8_t *ff_addr = (uint8_t *)host_addr; 15680Sstevel@tonic-gate for (i = 0; i < size; i++) 15690Sstevel@tonic-gate *ff_addr++ = 0xff; 15700Sstevel@tonic-gate 15710Sstevel@tonic-gate err = DDI_FAILURE; 15720Sstevel@tonic-gate #ifdef DEBUG 15730Sstevel@tonic-gate px_peekfault_cnt++; 15740Sstevel@tonic-gate #endif 15750Sstevel@tonic-gate } 15760Sstevel@tonic-gate } else { 15770Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) { 15780Sstevel@tonic-gate for (; repcount; repcount--) { 15790Sstevel@tonic-gate i_ddi_caut_get(size, (void *)dev_addr, 15800Sstevel@tonic-gate (void *)host_addr); 15810Sstevel@tonic-gate 15820Sstevel@tonic-gate host_addr += size; 15830Sstevel@tonic-gate 15840Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR) 15850Sstevel@tonic-gate dev_addr += size; 15860Sstevel@tonic-gate } 15870Sstevel@tonic-gate } else { 15880Sstevel@tonic-gate err = DDI_FAILURE; 15890Sstevel@tonic-gate #ifdef DEBUG 15900Sstevel@tonic-gate px_peekfault_cnt++; 15910Sstevel@tonic-gate #endif 15920Sstevel@tonic-gate } 15930Sstevel@tonic-gate } 15940Sstevel@tonic-gate 15950Sstevel@tonic-gate i_ddi_notrap((ddi_acc_handle_t)hp); 15960Sstevel@tonic-gate pec_p->pec_ontrap_data = NULL; 1597*27Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED; 15980Sstevel@tonic-gate i_ndi_busop_access_exit(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp); 15990Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_UNEXPECTED; 16000Sstevel@tonic-gate 16010Sstevel@tonic-gate return (err); 16020Sstevel@tonic-gate } 16030Sstevel@tonic-gate 16040Sstevel@tonic-gate /*ARGSUSED*/ 16050Sstevel@tonic-gate int 16060Sstevel@tonic-gate px_lib_ctlops_peek(dev_info_t *dip, dev_info_t *rdip, 16070Sstevel@tonic-gate peekpoke_ctlops_t *in_args, void *result) 16080Sstevel@tonic-gate { 16090Sstevel@tonic-gate result = (void *)in_args->host_addr; 16100Sstevel@tonic-gate return (in_args->handle ? px_lib_do_caut_get(dip, in_args) : 16110Sstevel@tonic-gate px_lib_do_peek(dip, in_args)); 16120Sstevel@tonic-gate } 16130Sstevel@tonic-gate /* 16140Sstevel@tonic-gate * implements PPM interface 16150Sstevel@tonic-gate */ 16160Sstevel@tonic-gate int 16170Sstevel@tonic-gate px_lib_pmctl(int cmd, px_t *px_p) 16180Sstevel@tonic-gate { 16190Sstevel@tonic-gate ASSERT((cmd & ~PPMREQ_MASK) == PPMREQ); 16200Sstevel@tonic-gate switch (cmd) { 16210Sstevel@tonic-gate case PPMREQ_PRE_PWR_OFF: 16220Sstevel@tonic-gate /* 16230Sstevel@tonic-gate * Currently there is no device power management for 16240Sstevel@tonic-gate * the root complex (fire). When there is we need to make 16250Sstevel@tonic-gate * sure that it is at full power before trying to send the 16260Sstevel@tonic-gate * PME_Turn_Off message. 16270Sstevel@tonic-gate */ 16280Sstevel@tonic-gate DBG(DBG_PWR, px_p->px_dip, 16290Sstevel@tonic-gate "ioctl: request to send PME_Turn_Off\n"); 16300Sstevel@tonic-gate return (px_goto_l23ready(px_p)); 16310Sstevel@tonic-gate 16320Sstevel@tonic-gate case PPMREQ_PRE_PWR_ON: 16330Sstevel@tonic-gate case PPMREQ_POST_PWR_ON: 16340Sstevel@tonic-gate /* code to be written for Fire 2.0. return failure for now */ 16350Sstevel@tonic-gate return (DDI_FAILURE); 16360Sstevel@tonic-gate 16370Sstevel@tonic-gate default: 16380Sstevel@tonic-gate return (DDI_FAILURE); 16390Sstevel@tonic-gate } 16400Sstevel@tonic-gate } 16410Sstevel@tonic-gate 16420Sstevel@tonic-gate /* 16430Sstevel@tonic-gate * sends PME_Turn_Off message to put the link in L2/L3 ready state. 16440Sstevel@tonic-gate * called by px_ioctl. 16450Sstevel@tonic-gate * returns DDI_SUCCESS or DDI_FAILURE 16460Sstevel@tonic-gate * 1. Wait for link to be in L1 state (link status reg) 16470Sstevel@tonic-gate * 2. write to PME_Turn_off reg to boradcast 16480Sstevel@tonic-gate * 3. set timeout 16490Sstevel@tonic-gate * 4. If timeout, return failure. 16500Sstevel@tonic-gate * 5. If PM_TO_Ack, wait till link is in L2/L3 ready 16510Sstevel@tonic-gate */ 16520Sstevel@tonic-gate static int 16530Sstevel@tonic-gate px_goto_l23ready(px_t *px_p) 16540Sstevel@tonic-gate { 16550Sstevel@tonic-gate pcie_pwr_t *pwr_p; 1656*27Sjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p; 1657*27Sjchu caddr_t csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR]; 16580Sstevel@tonic-gate int ret = DDI_SUCCESS; 16590Sstevel@tonic-gate clock_t end, timeleft; 16600Sstevel@tonic-gate 16610Sstevel@tonic-gate /* If no PM info, return failure */ 16620Sstevel@tonic-gate if (!PCIE_PMINFO(px_p->px_dip) || 16630Sstevel@tonic-gate !(pwr_p = PCIE_NEXUS_PMINFO(px_p->px_dip))) 16640Sstevel@tonic-gate return (DDI_FAILURE); 16650Sstevel@tonic-gate 16660Sstevel@tonic-gate mutex_enter(&pwr_p->pwr_lock); 16670Sstevel@tonic-gate mutex_enter(&pwr_p->pwr_intr_lock); 16680Sstevel@tonic-gate /* Clear the PME_To_ACK receieved flag */ 16690Sstevel@tonic-gate pwr_p->pwr_flags &= ~PCIE_PMETOACK_RECVD; 16700Sstevel@tonic-gate if (px_send_pme_turnoff(csr_base) != DDI_SUCCESS) { 16710Sstevel@tonic-gate ret = DDI_FAILURE; 16720Sstevel@tonic-gate goto l23ready_done; 16730Sstevel@tonic-gate } 16740Sstevel@tonic-gate pwr_p->pwr_flags |= PCIE_PME_TURNOFF_PENDING; 16750Sstevel@tonic-gate 16760Sstevel@tonic-gate end = ddi_get_lbolt() + drv_usectohz(px_pme_to_ack_timeout); 16770Sstevel@tonic-gate while (!(pwr_p->pwr_flags & PCIE_PMETOACK_RECVD)) { 16780Sstevel@tonic-gate timeleft = cv_timedwait(&pwr_p->pwr_cv, 16790Sstevel@tonic-gate &pwr_p->pwr_intr_lock, end); 16800Sstevel@tonic-gate /* 16810Sstevel@tonic-gate * if cv_timedwait returns -1, it is either 16820Sstevel@tonic-gate * 1) timed out or 16830Sstevel@tonic-gate * 2) there was a pre-mature wakeup but by the time 16840Sstevel@tonic-gate * cv_timedwait is called again end < lbolt i.e. 16850Sstevel@tonic-gate * end is in the past. 16860Sstevel@tonic-gate * 3) By the time we make first cv_timedwait call, 16870Sstevel@tonic-gate * end < lbolt is true. 16880Sstevel@tonic-gate */ 16890Sstevel@tonic-gate if (timeleft == -1) 16900Sstevel@tonic-gate break; 16910Sstevel@tonic-gate } 16920Sstevel@tonic-gate if (!(pwr_p->pwr_flags & PCIE_PMETOACK_RECVD)) { 16930Sstevel@tonic-gate /* 16940Sstevel@tonic-gate * Either timedout or interrupt didn't get a 16950Sstevel@tonic-gate * chance to grab the mutex and set the flag. 16960Sstevel@tonic-gate * release the mutex and delay for sometime. 16970Sstevel@tonic-gate * This will 1) give a chance for interrupt to 16980Sstevel@tonic-gate * set the flag 2) creates a delay between two 16990Sstevel@tonic-gate * consequetive requests. 17000Sstevel@tonic-gate */ 17010Sstevel@tonic-gate mutex_exit(&pwr_p->pwr_intr_lock); 17020Sstevel@tonic-gate delay(5); 17030Sstevel@tonic-gate mutex_enter(&pwr_p->pwr_intr_lock); 17040Sstevel@tonic-gate if (!(pwr_p->pwr_flags & PCIE_PMETOACK_RECVD)) { 17050Sstevel@tonic-gate ret = DDI_FAILURE; 17060Sstevel@tonic-gate DBG(DBG_PWR, px_p->px_dip, " Timed out while waiting" 17070Sstevel@tonic-gate " for PME_TO_ACK\n"); 17080Sstevel@tonic-gate } 17090Sstevel@tonic-gate } 17100Sstevel@tonic-gate /* PME_To_ACK receieved */ 17110Sstevel@tonic-gate pwr_p->pwr_flags &= ~(PCIE_PME_TURNOFF_PENDING | PCIE_PMETOACK_RECVD); 17120Sstevel@tonic-gate 17130Sstevel@tonic-gate /* TBD: wait till link is in L2/L3 ready (link status reg) */ 17140Sstevel@tonic-gate 17150Sstevel@tonic-gate l23ready_done: 17160Sstevel@tonic-gate mutex_exit(&pwr_p->pwr_intr_lock); 17170Sstevel@tonic-gate mutex_exit(&pwr_p->pwr_lock); 17180Sstevel@tonic-gate return (ret); 17190Sstevel@tonic-gate } 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate 17220Sstevel@tonic-gate /* 17230Sstevel@tonic-gate * Extract the drivers binding name to identify which chip we're binding to. 17240Sstevel@tonic-gate * Whenever a new bus bridge is created, the driver alias entry should be 17250Sstevel@tonic-gate * added here to identify the device if needed. If a device isn't added, 17260Sstevel@tonic-gate * the identity defaults to PX_CHIP_UNIDENTIFIED. 17270Sstevel@tonic-gate */ 17280Sstevel@tonic-gate static uint32_t 17290Sstevel@tonic-gate px_identity_chip(px_t *px_p) 17300Sstevel@tonic-gate { 17310Sstevel@tonic-gate dev_info_t *dip = px_p->px_dip; 17320Sstevel@tonic-gate char *name = ddi_binding_name(dip); 17330Sstevel@tonic-gate uint32_t revision = 0; 17340Sstevel@tonic-gate 17350Sstevel@tonic-gate revision = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 17360Sstevel@tonic-gate "module-revision#", 0); 17370Sstevel@tonic-gate 17380Sstevel@tonic-gate /* Check for Fire driver binding name */ 17390Sstevel@tonic-gate if (strcmp(name, "pci108e,80f0") == 0) { 17400Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_identity_chip: %s%d: " 17410Sstevel@tonic-gate "name %s module-revision %d\n", ddi_driver_name(dip), 17420Sstevel@tonic-gate ddi_get_instance(dip), name, revision); 17430Sstevel@tonic-gate 17440Sstevel@tonic-gate return (PX_CHIP_ID(PX_CHIP_FIRE, revision, 0x00)); 17450Sstevel@tonic-gate } 17460Sstevel@tonic-gate 17470Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "%s%d: Unknown PCI Express Host bridge %s %x\n", 17480Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip), name, revision); 17490Sstevel@tonic-gate 17500Sstevel@tonic-gate return (PX_CHIP_UNIDENTIFIED); 17510Sstevel@tonic-gate } 1752*27Sjchu 1753*27Sjchu int 1754*27Sjchu px_err_add_intr(px_fault_t *px_fault_p) 1755*27Sjchu { 1756*27Sjchu dev_info_t *dip = px_fault_p->px_fh_dip; 1757*27Sjchu px_t *px_p = DIP_TO_STATE(dip); 1758*27Sjchu 1759*27Sjchu VERIFY(add_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL, 1760*27Sjchu px_fault_p->px_err_func, (caddr_t)px_fault_p, NULL) == 0); 1761*27Sjchu 1762*27Sjchu px_ib_intr_enable(px_p, intr_dist_cpuid(), px_fault_p->px_intr_ino); 1763*27Sjchu 1764*27Sjchu return (DDI_SUCCESS); 1765*27Sjchu } 1766*27Sjchu 1767*27Sjchu void 1768*27Sjchu px_err_rem_intr(px_fault_t *px_fault_p) 1769*27Sjchu { 1770*27Sjchu dev_info_t *dip = px_fault_p->px_fh_dip; 1771*27Sjchu px_t *px_p = DIP_TO_STATE(dip); 1772*27Sjchu 1773*27Sjchu rem_ivintr(px_fault_p->px_fh_sysino, NULL); 1774*27Sjchu 1775*27Sjchu px_ib_intr_disable(px_p->px_ib_p, px_fault_p->px_intr_ino, 1776*27Sjchu IB_INTR_WAIT); 1777*27Sjchu } 1778*27Sjchu 1779*27Sjchu #ifdef FMA 1780*27Sjchu void 1781*27Sjchu px_fill_rc_status(px_fault_t *px_fault_p, pciex_rc_error_regs_t *rc_status) 1782*27Sjchu { 1783*27Sjchu /* populate the rc_status by reading the registers - TBD */ 1784*27Sjchu } 1785*27Sjchu #endif /* FMA */ 1786