xref: /onnv-gate/usr/src/uts/sun4v/io/px/px_lib4v.c (revision 12619:60877912fc2d)
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
51540Skini  * Common Development and Distribution License (the "License").
61540Skini  * 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 /*
2212262SAlan.Adamson@Sun.COM  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #include <sys/types.h>
260Sstevel@tonic-gate #include <sys/sysmacros.h>
270Sstevel@tonic-gate #include <sys/ddi.h>
28965Sgovinda #include <sys/async.h>
290Sstevel@tonic-gate #include <sys/sunddi.h>
300Sstevel@tonic-gate #include <sys/ddifm.h>
310Sstevel@tonic-gate #include <sys/fm/protocol.h>
320Sstevel@tonic-gate #include <sys/vmem.h>
3327Sjchu #include <sys/intr.h>
3427Sjchu #include <sys/ivintr.h>
3527Sjchu #include <sys/errno.h>
360Sstevel@tonic-gate #include <sys/hypervisor_api.h>
371617Sgovinda #include <sys/hsvc.h>
380Sstevel@tonic-gate #include <px_obj.h>
3927Sjchu #include <sys/machsystm.h>
4011596SJason.Beloro@Sun.COM #include <sys/sunndi.h>
4111596SJason.Beloro@Sun.COM #include <sys/pcie_impl.h>
420Sstevel@tonic-gate #include "px_lib4v.h"
4327Sjchu #include "px_err.h"
4411245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc.h>
4511245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc_4v.h>
4611245SZhijun.Fu@Sun.COM 
470Sstevel@tonic-gate 
480Sstevel@tonic-gate /* mask for the ranges property in calculating the real PFN range */
490Sstevel@tonic-gate uint_t px_ranges_phi_mask = ((1 << 28) -1);
500Sstevel@tonic-gate 
511617Sgovinda /*
521617Sgovinda  * Hypervisor VPCI services information for the px nexus driver.
531617Sgovinda  */
5412262SAlan.Adamson@Sun.COM static	uint64_t	px_vpci_maj_ver; /* Negotiated VPCI API major version */
551617Sgovinda static	uint64_t	px_vpci_min_ver; /* Negotiated VPCI API minor version */
561617Sgovinda static	uint_t		px_vpci_users = 0; /* VPCI API users */
5711596SJason.Beloro@Sun.COM static	hsvc_info_t px_hsvc_vpci = {
581617Sgovinda 	HSVC_REV_1, NULL, HSVC_GROUP_VPCI, PX_VPCI_MAJOR_VER,
591617Sgovinda 	PX_VPCI_MINOR_VER, "PX"
601617Sgovinda };
611617Sgovinda 
6211596SJason.Beloro@Sun.COM /*
6311596SJason.Beloro@Sun.COM  * Hypervisor SDIO services information for the px nexus driver.
6411596SJason.Beloro@Sun.COM  */
6511596SJason.Beloro@Sun.COM static	uint64_t	px_sdio_min_ver; /* Negotiated SDIO API minor version */
6611596SJason.Beloro@Sun.COM static	uint_t		px_sdio_users = 0; /* SDIO API users */
6711596SJason.Beloro@Sun.COM static	hsvc_info_t px_hsvc_sdio = {
6811596SJason.Beloro@Sun.COM 	HSVC_REV_1, NULL, HSVC_GROUP_SDIO, PX_SDIO_MAJOR_VER,
6911596SJason.Beloro@Sun.COM 	PX_SDIO_MINOR_VER, "PX"
7011596SJason.Beloro@Sun.COM };
7111596SJason.Beloro@Sun.COM 
7211596SJason.Beloro@Sun.COM /*
7311596SJason.Beloro@Sun.COM  * Hypervisor SDIO ERR services information for the px nexus driver.
7411596SJason.Beloro@Sun.COM  */
7511596SJason.Beloro@Sun.COM static	uint64_t	px_sdio_err_min_ver; /* Negotiated SDIO ERR API */
7611596SJason.Beloro@Sun.COM 						/* minor version */
7711596SJason.Beloro@Sun.COM static	uint_t		px_sdio_err_users = 0; /* SDIO ERR API users */
7811596SJason.Beloro@Sun.COM static	hsvc_info_t px_hsvc_sdio_err = {
7911596SJason.Beloro@Sun.COM 	HSVC_REV_1, NULL, HSVC_GROUP_SDIO_ERR, PX_SDIO_ERR_MAJOR_VER,
8011596SJason.Beloro@Sun.COM 	PX_SDIO_ERR_MINOR_VER, "PX"
8111596SJason.Beloro@Sun.COM };
8211596SJason.Beloro@Sun.COM 
8311596SJason.Beloro@Sun.COM #define	CHILD_LOANED	"child_loaned"
8411596SJason.Beloro@Sun.COM static int px_lib_count_waiting_dev(dev_info_t *);
8511596SJason.Beloro@Sun.COM 
860Sstevel@tonic-gate int
px_lib_dev_init(dev_info_t * dip,devhandle_t * dev_hdl)870Sstevel@tonic-gate px_lib_dev_init(dev_info_t *dip, devhandle_t *dev_hdl)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate 	px_nexus_regspec_t	*rp;
90226Set142600 	uint_t			reglen;
91226Set142600 	int			ret;
9211596SJason.Beloro@Sun.COM 	px_t			*px_p = DIP_TO_STATE(dip);
934423Sjb145095 	uint64_t mjrnum;
944423Sjb145095 	uint64_t mnrnum;
954423Sjb145095 
960Sstevel@tonic-gate 	DBG(DBG_ATTACH, dip, "px_lib_dev_init: dip 0x%p\n", dip);
970Sstevel@tonic-gate 
984423Sjb145095 	/*
994423Sjb145095 	 * Check HV intr group api versioning.
1004423Sjb145095 	 * This driver uses the old interrupt routines which are supported
1014423Sjb145095 	 * in old firmware in the CORE API group and in newer firmware in
1024423Sjb145095 	 * the INTR API group.  Support for these calls will be dropped
1034423Sjb145095 	 * once the INTR API group major goes to 2.
1044423Sjb145095 	 */
1054423Sjb145095 	if ((hsvc_version(HSVC_GROUP_INTR, &mjrnum, &mnrnum) == 0) &&
1064423Sjb145095 	    (mjrnum > 1)) {
10711074SZachary.Kissel@Sun.COM 		cmn_err(CE_WARN, "px: unsupported intr api group: "
1084423Sjb145095 		    "maj:0x%lx, min:0x%lx", mjrnum, mnrnum);
1094423Sjb145095 		return (ENOTSUP);
1104423Sjb145095 	}
1114423Sjb145095 
112226Set142600 	ret = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
113226Set142600 	    "reg", (uchar_t **)&rp, &reglen);
114226Set142600 	if (ret != DDI_PROP_SUCCESS) {
115226Set142600 		DBG(DBG_ATTACH, dip, "px_lib_dev_init failed ret=%d\n", ret);
1160Sstevel@tonic-gate 		return (DDI_FAILURE);
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	/*
1200Sstevel@tonic-gate 	 * Initilize device handle. The device handle uniquely identifies
1210Sstevel@tonic-gate 	 * a SUN4V device. It consists of the lower 28-bits of the hi-cell
1220Sstevel@tonic-gate 	 * of the first entry of the SUN4V device's "reg" property as
1230Sstevel@tonic-gate 	 * defined by the SUN4V Bus Binding to Open Firmware.
1240Sstevel@tonic-gate 	 */
1250Sstevel@tonic-gate 	*dev_hdl = (devhandle_t)((rp->phys_addr >> 32) & DEVHDLE_MASK);
126226Set142600 	ddi_prop_free(rp);
127226Set142600 
1281531Skini 	/*
1291531Skini 	 * hotplug implementation requires this property to be associated with
1301531Skini 	 * any indirect PCI config access services
1311531Skini 	 */
1321531Skini 	(void) ddi_prop_update_int(makedevice(ddi_driver_major(dip),
13310923SEvan.Yan@Sun.COM 	    PCI_MINOR_NUM(ddi_get_instance(dip), PCI_DEVCTL_MINOR)), dip,
1341531Skini 	    PCI_BUS_CONF_MAP_PROP, 1);
1351531Skini 
1360Sstevel@tonic-gate 	DBG(DBG_ATTACH, dip, "px_lib_dev_init: dev_hdl 0x%llx\n", *dev_hdl);
1370Sstevel@tonic-gate 
1381617Sgovinda 	/*
13911596SJason.Beloro@Sun.COM 	 * If a /pci node has a pci-intx-not-supported property, this property
14011596SJason.Beloro@Sun.COM 	 * represents that the fabric doesn't support fixed interrupt.
14111596SJason.Beloro@Sun.COM 	 */
14211596SJason.Beloro@Sun.COM 	if (!ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
14311596SJason.Beloro@Sun.COM 	    "pci-intx-not-supported")) {
14411596SJason.Beloro@Sun.COM 		DBG(DBG_ATTACH, dip, "px_lib_dev_init: "
14511596SJason.Beloro@Sun.COM 		    "pci-intx-not-supported is not found, dip=0x%p\n", dip);
14611596SJason.Beloro@Sun.COM 		px_p->px_supp_intr_types |= DDI_INTR_TYPE_FIXED;
14711596SJason.Beloro@Sun.COM 	}
14811596SJason.Beloro@Sun.COM 
14911596SJason.Beloro@Sun.COM 	/*
1501617Sgovinda 	 * Negotiate the API version for VPCI hypervisor services.
1511617Sgovinda 	 */
15212262SAlan.Adamson@Sun.COM 	if (px_vpci_users == 0) {
15312262SAlan.Adamson@Sun.COM 		if ((ret = hsvc_register(&px_hsvc_vpci, &px_vpci_min_ver))
15412262SAlan.Adamson@Sun.COM 		    == 0) {
15512262SAlan.Adamson@Sun.COM 			px_vpci_maj_ver = px_hsvc_vpci.hsvc_major;
15612262SAlan.Adamson@Sun.COM 			goto hv_negotiation_complete;
15712262SAlan.Adamson@Sun.COM 		}
15812262SAlan.Adamson@Sun.COM 		/*
15912262SAlan.Adamson@Sun.COM 		 * Negotiation with the latest known VPCI hypervisor services
16012262SAlan.Adamson@Sun.COM 		 * failed.  Fallback to version 1.0.
16112262SAlan.Adamson@Sun.COM 		 */
16212262SAlan.Adamson@Sun.COM 		px_hsvc_vpci.hsvc_major = PX_HSVC_MAJOR_VER_1;
16312262SAlan.Adamson@Sun.COM 		px_hsvc_vpci.hsvc_minor = PX_HSVC_MINOR_VER_0;
16412262SAlan.Adamson@Sun.COM 
16512262SAlan.Adamson@Sun.COM 		if ((ret = hsvc_register(&px_hsvc_vpci, &px_vpci_min_ver))
16612262SAlan.Adamson@Sun.COM 		    == 0) {
16712262SAlan.Adamson@Sun.COM 			px_vpci_maj_ver = px_hsvc_vpci.hsvc_major;
16812262SAlan.Adamson@Sun.COM 			goto hv_negotiation_complete;
16912262SAlan.Adamson@Sun.COM 		}
17012262SAlan.Adamson@Sun.COM 
1711617Sgovinda 		cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
1721617Sgovinda 		    "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d\n",
17311596SJason.Beloro@Sun.COM 		    px_hsvc_vpci.hsvc_modname, px_hsvc_vpci.hsvc_group,
17411596SJason.Beloro@Sun.COM 		    px_hsvc_vpci.hsvc_major, px_hsvc_vpci.hsvc_minor, ret);
17512262SAlan.Adamson@Sun.COM 
1761617Sgovinda 		return (DDI_FAILURE);
1771617Sgovinda 	}
17812262SAlan.Adamson@Sun.COM hv_negotiation_complete:
17912262SAlan.Adamson@Sun.COM 
18011596SJason.Beloro@Sun.COM 	px_vpci_users++;
18112262SAlan.Adamson@Sun.COM 
1821617Sgovinda 	DBG(DBG_ATTACH, dip, "px_lib_dev_init: negotiated VPCI API version, "
18312262SAlan.Adamson@Sun.COM 	    "major 0x%lx minor 0x%lx\n", px_vpci_maj_ver,
18411596SJason.Beloro@Sun.COM 	    px_vpci_min_ver);
18511596SJason.Beloro@Sun.COM 
18611596SJason.Beloro@Sun.COM 	/*
18711596SJason.Beloro@Sun.COM 	 * Negotiate the API version for SDIO hypervisor services.
18811596SJason.Beloro@Sun.COM 	 */
18911596SJason.Beloro@Sun.COM 	if ((px_sdio_users == 0) &&
19011596SJason.Beloro@Sun.COM 	    ((ret = hsvc_register(&px_hsvc_sdio, &px_sdio_min_ver)) != 0)) {
19111596SJason.Beloro@Sun.COM 		DBG(DBG_ATTACH, dip, "%s: cannot negotiate hypervisor "
19211596SJason.Beloro@Sun.COM 		    "services group: 0x%lx major: 0x%lx minor: 0x%lx "
19311596SJason.Beloro@Sun.COM 		    "errno: %d\n", px_hsvc_sdio.hsvc_modname,
19411596SJason.Beloro@Sun.COM 		    px_hsvc_sdio.hsvc_group, px_hsvc_sdio.hsvc_major,
19511596SJason.Beloro@Sun.COM 		    px_hsvc_sdio.hsvc_minor, ret);
19611596SJason.Beloro@Sun.COM 	} else {
19711596SJason.Beloro@Sun.COM 		px_sdio_users++;
19811596SJason.Beloro@Sun.COM 		DBG(DBG_ATTACH, dip, "px_lib_dev_init: negotiated SDIO API"
19911596SJason.Beloro@Sun.COM 		    "version, major 0x%lx minor 0x%lx\n",
20011596SJason.Beloro@Sun.COM 		    px_hsvc_sdio.hsvc_major, px_sdio_min_ver);
20111596SJason.Beloro@Sun.COM 	}
2021617Sgovinda 
20311596SJason.Beloro@Sun.COM 	/*
20411596SJason.Beloro@Sun.COM 	 * Negotiate the API version for SDIO ERR hypervisor services.
20511596SJason.Beloro@Sun.COM 	 */
20611596SJason.Beloro@Sun.COM 	if ((px_sdio_err_users == 0) &&
20711596SJason.Beloro@Sun.COM 	    ((ret = hsvc_register(&px_hsvc_sdio_err,
20811596SJason.Beloro@Sun.COM 	    &px_sdio_err_min_ver)) != 0)) {
20911596SJason.Beloro@Sun.COM 		DBG(DBG_ATTACH, dip, "%s: cannot negotiate SDIO ERR hypervisor "
21011596SJason.Beloro@Sun.COM 		    "services group: 0x%lx major: 0x%lx minor: 0x%lx "
21111596SJason.Beloro@Sun.COM 		    "errno: %d\n", px_hsvc_sdio_err.hsvc_modname,
21211596SJason.Beloro@Sun.COM 		    px_hsvc_sdio_err.hsvc_group, px_hsvc_sdio_err.hsvc_major,
21311596SJason.Beloro@Sun.COM 		    px_hsvc_sdio_err.hsvc_minor, ret);
21411596SJason.Beloro@Sun.COM 	} else {
21511596SJason.Beloro@Sun.COM 		px_sdio_err_users++;
21611596SJason.Beloro@Sun.COM 		DBG(DBG_ATTACH, dip, "px_lib_dev_init: negotiated SDIO ERR API "
21711596SJason.Beloro@Sun.COM 		    "version, major 0x%lx minor 0x%lx\n",
21811596SJason.Beloro@Sun.COM 		    px_hsvc_sdio_err.hsvc_major, px_sdio_err_min_ver);
21911596SJason.Beloro@Sun.COM 	}
22011596SJason.Beloro@Sun.COM 
22111596SJason.Beloro@Sun.COM 	/*
22211596SJason.Beloro@Sun.COM 	 * Find out the number of dev we need to wait under this RC
22311596SJason.Beloro@Sun.COM 	 * before we issue fabric sync hypercall
22411596SJason.Beloro@Sun.COM 	 */
22511596SJason.Beloro@Sun.COM 	px_p->px_plat_p = (void *)(uintptr_t)px_lib_count_waiting_dev(dip);
22611596SJason.Beloro@Sun.COM 	DBG(DBG_ATTACH, dip, "Found %d bridges need waiting under RC %p",
22711596SJason.Beloro@Sun.COM 	    (int)(uintptr_t)px_p->px_plat_p, dip);
2280Sstevel@tonic-gate 	return (DDI_SUCCESS);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate /*ARGSUSED*/
2320Sstevel@tonic-gate int
px_lib_dev_fini(dev_info_t * dip)2330Sstevel@tonic-gate px_lib_dev_fini(dev_info_t *dip)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate 	DBG(DBG_DETACH, dip, "px_lib_dev_fini: dip 0x%p\n", dip);
2360Sstevel@tonic-gate 
2371531Skini 	(void) ddi_prop_remove(makedevice(ddi_driver_major(dip),
23810923SEvan.Yan@Sun.COM 	    PCI_MINOR_NUM(ddi_get_instance(dip), PCI_DEVCTL_MINOR)), dip,
2391531Skini 	    PCI_BUS_CONF_MAP_PROP);
2401531Skini 
2411617Sgovinda 	if (--px_vpci_users == 0)
24211596SJason.Beloro@Sun.COM 		(void) hsvc_unregister(&px_hsvc_vpci);
24311596SJason.Beloro@Sun.COM 
24411596SJason.Beloro@Sun.COM 	if (--px_sdio_users == 0)
24511596SJason.Beloro@Sun.COM 		(void) hsvc_unregister(&px_hsvc_sdio);
24611596SJason.Beloro@Sun.COM 
24711596SJason.Beloro@Sun.COM 	if (--px_sdio_err_users == 0)
24811596SJason.Beloro@Sun.COM 		(void) hsvc_unregister(&px_hsvc_sdio_err);
2491617Sgovinda 
2500Sstevel@tonic-gate 	return (DDI_SUCCESS);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate /*ARGSUSED*/
2540Sstevel@tonic-gate int
px_lib_intr_devino_to_sysino(dev_info_t * dip,devino_t devino,sysino_t * sysino)2550Sstevel@tonic-gate px_lib_intr_devino_to_sysino(dev_info_t *dip, devino_t devino,
2560Sstevel@tonic-gate     sysino_t *sysino)
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate 	uint64_t	ret;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: dip 0x%p "
2610Sstevel@tonic-gate 	    "devino 0x%x\n", dip, devino);
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	if ((ret = hvio_intr_devino_to_sysino(DIP_TO_HANDLE(dip),
2640Sstevel@tonic-gate 	    devino, sysino)) != H_EOK) {
2650Sstevel@tonic-gate 		DBG(DBG_LIB_INT, dip,
2660Sstevel@tonic-gate 		    "hvio_intr_devino_to_sysino failed, ret 0x%lx\n", ret);
2670Sstevel@tonic-gate 		return (DDI_FAILURE);
2680Sstevel@tonic-gate 	}
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: sysino 0x%llx\n",
2710Sstevel@tonic-gate 	    *sysino);
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	return (DDI_SUCCESS);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate /*ARGSUSED*/
2770Sstevel@tonic-gate int
px_lib_intr_getvalid(dev_info_t * dip,sysino_t sysino,intr_valid_state_t * intr_valid_state)2780Sstevel@tonic-gate px_lib_intr_getvalid(dev_info_t *dip, sysino_t sysino,
2790Sstevel@tonic-gate     intr_valid_state_t *intr_valid_state)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate 	uint64_t	ret;
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: dip 0x%p sysino 0x%llx\n",
2840Sstevel@tonic-gate 	    dip, sysino);
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	if ((ret = hvio_intr_getvalid(sysino,
2870Sstevel@tonic-gate 	    (int *)intr_valid_state)) != H_EOK) {
2880Sstevel@tonic-gate 		DBG(DBG_LIB_INT, dip, "hvio_intr_getvalid failed, ret 0x%lx\n",
2890Sstevel@tonic-gate 		    ret);
2900Sstevel@tonic-gate 		return (DDI_FAILURE);
2910Sstevel@tonic-gate 	}
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: intr_valid_state 0x%x\n",
2940Sstevel@tonic-gate 	    *intr_valid_state);
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	return (DDI_SUCCESS);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate /*ARGSUSED*/
3000Sstevel@tonic-gate int
px_lib_intr_setvalid(dev_info_t * dip,sysino_t sysino,intr_valid_state_t intr_valid_state)3010Sstevel@tonic-gate px_lib_intr_setvalid(dev_info_t *dip, sysino_t sysino,
3020Sstevel@tonic-gate     intr_valid_state_t intr_valid_state)
3030Sstevel@tonic-gate {
3040Sstevel@tonic-gate 	uint64_t	ret;
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_setvalid: dip 0x%p sysino 0x%llx "
3070Sstevel@tonic-gate 	    "intr_valid_state 0x%x\n", dip, sysino, intr_valid_state);
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if ((ret = hvio_intr_setvalid(sysino, intr_valid_state)) != H_EOK) {
3100Sstevel@tonic-gate 		DBG(DBG_LIB_INT, dip, "hvio_intr_setvalid failed, ret 0x%lx\n",
3110Sstevel@tonic-gate 		    ret);
3120Sstevel@tonic-gate 		return (DDI_FAILURE);
3130Sstevel@tonic-gate 	}
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	return (DDI_SUCCESS);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate /*ARGSUSED*/
3190Sstevel@tonic-gate int
px_lib_intr_getstate(dev_info_t * dip,sysino_t sysino,intr_state_t * intr_state)3200Sstevel@tonic-gate px_lib_intr_getstate(dev_info_t *dip, sysino_t sysino,
3210Sstevel@tonic-gate     intr_state_t *intr_state)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate 	uint64_t	ret;
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: dip 0x%p sysino 0x%llx\n",
3260Sstevel@tonic-gate 	    dip, sysino);
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	if ((ret = hvio_intr_getstate(sysino, (int *)intr_state)) != H_EOK) {
3290Sstevel@tonic-gate 		DBG(DBG_LIB_INT, dip, "hvio_intr_getstate failed, ret 0x%lx\n",
3300Sstevel@tonic-gate 		    ret);
3310Sstevel@tonic-gate 		return (DDI_FAILURE);
3320Sstevel@tonic-gate 	}
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: intr_state 0x%x\n",
3350Sstevel@tonic-gate 	    *intr_state);
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	return (DDI_SUCCESS);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate /*ARGSUSED*/
3410Sstevel@tonic-gate int
px_lib_intr_setstate(dev_info_t * dip,sysino_t sysino,intr_state_t intr_state)3420Sstevel@tonic-gate px_lib_intr_setstate(dev_info_t *dip, sysino_t sysino,
3430Sstevel@tonic-gate     intr_state_t intr_state)
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate 	uint64_t	ret;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_setstate: dip 0x%p sysino 0x%llx "
3480Sstevel@tonic-gate 	    "intr_state 0x%x\n", dip, sysino, intr_state);
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	if ((ret = hvio_intr_setstate(sysino, intr_state)) != H_EOK) {
3510Sstevel@tonic-gate 		DBG(DBG_LIB_INT, dip, "hvio_intr_setstate failed, ret 0x%lx\n",
3520Sstevel@tonic-gate 		    ret);
3530Sstevel@tonic-gate 		return (DDI_FAILURE);
3540Sstevel@tonic-gate 	}
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 	return (DDI_SUCCESS);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate /*ARGSUSED*/
3600Sstevel@tonic-gate int
px_lib_intr_gettarget(dev_info_t * dip,sysino_t sysino,cpuid_t * cpuid)3610Sstevel@tonic-gate px_lib_intr_gettarget(dev_info_t *dip, sysino_t sysino, cpuid_t *cpuid)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate 	uint64_t	ret;
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: dip 0x%p sysino 0x%llx\n",
3660Sstevel@tonic-gate 	    dip, sysino);
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	if ((ret = hvio_intr_gettarget(sysino, cpuid)) != H_EOK) {
3690Sstevel@tonic-gate 		DBG(DBG_LIB_INT, dip,
3700Sstevel@tonic-gate 		    "hvio_intr_gettarget failed, ret 0x%lx\n", ret);
3710Sstevel@tonic-gate 		return (DDI_FAILURE);
3720Sstevel@tonic-gate 	}
3730Sstevel@tonic-gate 
37410053SEvan.Yan@Sun.COM 	DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: cpuid 0x%x\n", *cpuid);
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	return (DDI_SUCCESS);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate /*ARGSUSED*/
3800Sstevel@tonic-gate int
px_lib_intr_settarget(dev_info_t * dip,sysino_t sysino,cpuid_t cpuid)3810Sstevel@tonic-gate px_lib_intr_settarget(dev_info_t *dip, sysino_t sysino, cpuid_t cpuid)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	uint64_t	ret;
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_settarget: dip 0x%p sysino 0x%llx "
3860Sstevel@tonic-gate 	    "cpuid 0x%x\n", dip, sysino, cpuid);
3870Sstevel@tonic-gate 
3887124Sanbui 	ret = hvio_intr_settarget(sysino, cpuid);
3897124Sanbui 	if (ret == H_ECPUERROR) {
3907124Sanbui 		cmn_err(CE_PANIC,
3917124Sanbui 		    "px_lib_intr_settarget: hvio_intr_settarget failed, "
3927124Sanbui 		    "ret = 0x%lx, cpuid = 0x%x, sysino = 0x%lx\n", ret,
3937124Sanbui 		    cpuid, sysino);
3947124Sanbui 	} else if (ret != H_EOK) {
3950Sstevel@tonic-gate 		DBG(DBG_LIB_INT, dip,
3960Sstevel@tonic-gate 		    "hvio_intr_settarget failed, ret 0x%lx\n", ret);
3970Sstevel@tonic-gate 		return (DDI_FAILURE);
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	return (DDI_SUCCESS);
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate /*ARGSUSED*/
4040Sstevel@tonic-gate int
px_lib_intr_reset(dev_info_t * dip)4050Sstevel@tonic-gate px_lib_intr_reset(dev_info_t *dip)
4060Sstevel@tonic-gate {
4072973Sgovinda 	px_t		*px_p = DIP_TO_STATE(dip);
4082973Sgovinda 	px_ib_t		*ib_p = px_p->px_ib_p;
4092973Sgovinda 	px_ino_t	*ino_p;
410965Sgovinda 
4110Sstevel@tonic-gate 	DBG(DBG_LIB_INT, dip, "px_lib_intr_reset: dip 0x%p\n", dip);
4120Sstevel@tonic-gate 
413965Sgovinda 	mutex_enter(&ib_p->ib_ino_lst_mutex);
414965Sgovinda 
415965Sgovinda 	/* Reset all Interrupts */
4162973Sgovinda 	for (ino_p = ib_p->ib_ino_lst; ino_p; ino_p = ino_p->ino_next_p) {
417965Sgovinda 		if (px_lib_intr_setstate(dip, ino_p->ino_sysino,
418965Sgovinda 		    INTR_IDLE_STATE) != DDI_SUCCESS)
419965Sgovinda 			return (BF_FATAL);
420965Sgovinda 	}
421965Sgovinda 
422965Sgovinda 	mutex_exit(&ib_p->ib_ino_lst_mutex);
423965Sgovinda 
424965Sgovinda 	return (BF_NONE);
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate /*ARGSUSED*/
4280Sstevel@tonic-gate int
px_lib_iommu_map(dev_info_t * dip,tsbid_t tsbid,pages_t pages,io_attributes_t attr,void * addr,size_t pfn_index,int flags)4290Sstevel@tonic-gate px_lib_iommu_map(dev_info_t *dip, tsbid_t tsbid, pages_t pages,
4301617Sgovinda     io_attributes_t attr, void *addr, size_t pfn_index, int flags)
4310Sstevel@tonic-gate {
4320Sstevel@tonic-gate 	tsbnum_t	tsb_num = PCI_TSBID_TO_TSBNUM(tsbid);
4331057Sgovinda 	tsbindex_t	tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
4341057Sgovinda 	io_page_list_t	*pfns, *pfn_p;
4351057Sgovinda 	pages_t		ttes_mapped = 0;
4360Sstevel@tonic-gate 	int		i, err = DDI_SUCCESS;
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: dip 0x%p tsbid 0x%llx "
4399707SDaniel.Ice@Sun.COM 	    "pages 0x%x attr 0x%llx addr 0x%p pfn_index 0x%llx flags 0x%x\n",
4401617Sgovinda 	    dip, tsbid, pages, attr, addr, pfn_index, flags);
4410Sstevel@tonic-gate 
4421057Sgovinda 	if ((pfns = pfn_p = kmem_zalloc((pages * sizeof (io_page_list_t)),
4430Sstevel@tonic-gate 	    KM_NOSLEEP)) == NULL) {
4440Sstevel@tonic-gate 		DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: kmem_zalloc failed\n");
4450Sstevel@tonic-gate 		return (DDI_FAILURE);
4460Sstevel@tonic-gate 	}
4470Sstevel@tonic-gate 
4481057Sgovinda 	for (i = 0; i < pages; i++)
4491617Sgovinda 		pfns[i] = MMU_PTOB(PX_ADDR2PFN(addr, pfn_index, flags, i));
4500Sstevel@tonic-gate 
4511857Sam139583 	/*
45212262SAlan.Adamson@Sun.COM 	 * If HV VPCI version is 2.0 and higher, pass BDF, phantom function,
4533156Sgirish 	 * and relaxed ordering attributes. Otherwise, pass only read or write
4543156Sgirish 	 * attribute.
4551857Sam139583 	 */
45612262SAlan.Adamson@Sun.COM 	if ((px_vpci_maj_ver == PX_HSVC_MAJOR_VER_1) &&
45712262SAlan.Adamson@Sun.COM 	    (px_vpci_min_ver == PX_HSVC_MINOR_VER_0))
4581857Sam139583 		attr = attr & (PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE);
4591857Sam139583 
4601057Sgovinda 	while ((ttes_mapped = pfn_p - pfns) < pages) {
4611057Sgovinda 		uintptr_t	ra = va_to_pa(pfn_p);
4621057Sgovinda 		pages_t		ttes2map;
4631057Sgovinda 		uint64_t	ret;
4641057Sgovinda 
4651057Sgovinda 		ttes2map = (MMU_PAGE_SIZE - P2PHASE(ra, MMU_PAGE_SIZE)) >> 3;
4661057Sgovinda 		ra = MMU_PTOB(MMU_BTOP(ra));
4671057Sgovinda 
4681057Sgovinda 		for (ttes2map = MIN(ttes2map, pages - ttes_mapped); ttes2map;
4691057Sgovinda 		    ttes2map -= ttes_mapped, pfn_p += ttes_mapped) {
4700Sstevel@tonic-gate 
4711057Sgovinda 			ttes_mapped = 0;
4721057Sgovinda 			if ((ret = hvio_iommu_map(DIP_TO_HANDLE(dip),
4731057Sgovinda 			    PCI_TSBID(tsb_num, tsb_index + (pfn_p - pfns)),
4741617Sgovinda 			    ttes2map, attr, (io_page_list_t *)(ra |
4751057Sgovinda 			    ((uintptr_t)pfn_p & MMU_PAGE_OFFSET)),
4761057Sgovinda 			    &ttes_mapped)) != H_EOK) {
4771057Sgovinda 				DBG(DBG_LIB_DMA, dip, "hvio_iommu_map failed "
4781057Sgovinda 				    "ret 0x%lx\n", ret);
4790Sstevel@tonic-gate 
4801057Sgovinda 				ttes_mapped = pfn_p - pfns;
4811057Sgovinda 				err = DDI_FAILURE;
4821057Sgovinda 				goto cleanup;
4831057Sgovinda 			}
4841057Sgovinda 
4851057Sgovinda 			DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: tsb_num 0x%x "
4869707SDaniel.Ice@Sun.COM 			    "tsb_index 0x%lx ttes_to_map 0x%lx attr 0x%llx "
4871057Sgovinda 			    "ra 0x%p ttes_mapped 0x%x\n", tsb_num,
4881617Sgovinda 			    tsb_index + (pfn_p - pfns), ttes2map, attr,
4891057Sgovinda 			    ra | ((uintptr_t)pfn_p & MMU_PAGE_OFFSET),
4901057Sgovinda 			    ttes_mapped);
4910Sstevel@tonic-gate 		}
4920Sstevel@tonic-gate 	}
4930Sstevel@tonic-gate 
4941057Sgovinda cleanup:
4951057Sgovinda 	if ((err == DDI_FAILURE) && ttes_mapped)
4961057Sgovinda 		(void) px_lib_iommu_demap(dip, tsbid, ttes_mapped);
4970Sstevel@tonic-gate 
4981057Sgovinda 	kmem_free(pfns, pages * sizeof (io_page_list_t));
4990Sstevel@tonic-gate 	return (err);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate /*ARGSUSED*/
5030Sstevel@tonic-gate int
px_lib_iommu_demap(dev_info_t * dip,tsbid_t tsbid,pages_t pages)5040Sstevel@tonic-gate px_lib_iommu_demap(dev_info_t *dip, tsbid_t tsbid, pages_t pages)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate 	tsbnum_t	tsb_num = PCI_TSBID_TO_TSBNUM(tsbid);
5071057Sgovinda 	tsbindex_t	tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
5081057Sgovinda 	pages_t		ttes2demap, ttes_demapped = 0;
5090Sstevel@tonic-gate 	uint64_t	ret;
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: dip 0x%p tsbid 0x%llx "
5120Sstevel@tonic-gate 	    "pages 0x%x\n", dip, tsbid, pages);
5130Sstevel@tonic-gate 
5141057Sgovinda 	for (ttes2demap = pages; ttes2demap;
5151057Sgovinda 	    ttes2demap -= ttes_demapped, tsb_index += ttes_demapped) {
5160Sstevel@tonic-gate 		if ((ret = hvio_iommu_demap(DIP_TO_HANDLE(dip),
5171057Sgovinda 		    PCI_TSBID(tsb_num, tsb_index), ttes2demap,
5181057Sgovinda 		    &ttes_demapped)) != H_EOK) {
5191057Sgovinda 			DBG(DBG_LIB_DMA, dip, "hvio_iommu_demap failed, "
5201057Sgovinda 			    "ret 0x%lx\n", ret);
5211057Sgovinda 
5220Sstevel@tonic-gate 			return (DDI_FAILURE);
5230Sstevel@tonic-gate 		}
5240Sstevel@tonic-gate 
5251057Sgovinda 		DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: tsb_num 0x%x "
5261057Sgovinda 		    "tsb_index 0x%lx ttes_to_demap 0x%lx ttes_demapped 0x%x\n",
5271057Sgovinda 		    tsb_num, tsb_index, ttes2demap, ttes_demapped);
5280Sstevel@tonic-gate 	}
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	return (DDI_SUCCESS);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*ARGSUSED*/
5340Sstevel@tonic-gate int
px_lib_iommu_getmap(dev_info_t * dip,tsbid_t tsbid,io_attributes_t * attr_p,r_addr_t * r_addr_p)5351617Sgovinda px_lib_iommu_getmap(dev_info_t *dip, tsbid_t tsbid, io_attributes_t *attr_p,
5361617Sgovinda     r_addr_t *r_addr_p)
5370Sstevel@tonic-gate {
5380Sstevel@tonic-gate 	uint64_t	ret;
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: dip 0x%p tsbid 0x%llx\n",
5410Sstevel@tonic-gate 	    dip, tsbid);
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	if ((ret = hvio_iommu_getmap(DIP_TO_HANDLE(dip), tsbid,
5441617Sgovinda 	    attr_p, r_addr_p)) != H_EOK) {
5450Sstevel@tonic-gate 		DBG(DBG_LIB_DMA, dip,
5460Sstevel@tonic-gate 		    "hvio_iommu_getmap failed, ret 0x%lx\n", ret);
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 		return ((ret == H_ENOMAP) ? DDI_DMA_NOMAPPING:DDI_FAILURE);
5490Sstevel@tonic-gate 	}
5500Sstevel@tonic-gate 
5519707SDaniel.Ice@Sun.COM 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: attr 0x%llx "
5529707SDaniel.Ice@Sun.COM 	    "r_addr 0x%llx\n", *attr_p, *r_addr_p);
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	return (DDI_SUCCESS);
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate 
5571772Sjl139090 /*ARGSUSED*/
558*12619Sandrew.rutz@sun.com int
px_lib_iommu_detach(px_t * px_p)559*12619Sandrew.rutz@sun.com px_lib_iommu_detach(px_t *px_p)
560*12619Sandrew.rutz@sun.com {
561*12619Sandrew.rutz@sun.com 	return (DDI_SUCCESS);
562*12619Sandrew.rutz@sun.com }
563*12619Sandrew.rutz@sun.com 
564*12619Sandrew.rutz@sun.com /*ARGSUSED*/
5651772Sjl139090 uint64_t
px_get_rng_parent_hi_mask(px_t * px_p)5662053Sschwartz px_get_rng_parent_hi_mask(px_t *px_p)
5671772Sjl139090 {
5682053Sschwartz 	return (PX_RANGE_PROP_MASK);
5691772Sjl139090 }
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate /*
5720Sstevel@tonic-gate  * Checks dma attributes against system bypass ranges
5730Sstevel@tonic-gate  * A sun4v device must be capable of generating the entire 64-bit
5740Sstevel@tonic-gate  * address in order to perform bypass DMA.
5750Sstevel@tonic-gate  */
5760Sstevel@tonic-gate /*ARGSUSED*/
5770Sstevel@tonic-gate int
px_lib_dma_bypass_rngchk(dev_info_t * dip,ddi_dma_attr_t * attr_p,uint64_t * lo_p,uint64_t * hi_p)5781772Sjl139090 px_lib_dma_bypass_rngchk(dev_info_t *dip, ddi_dma_attr_t *attr_p,
5791772Sjl139090     uint64_t *lo_p, uint64_t *hi_p)
5800Sstevel@tonic-gate {
5811617Sgovinda 	if ((attr_p->dma_attr_addr_lo != 0ull) ||
5821617Sgovinda 	    (attr_p->dma_attr_addr_hi != UINT64_MAX)) {
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 		return (DDI_DMA_BADATTR);
5850Sstevel@tonic-gate 	}
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 	*lo_p = 0ull;
5880Sstevel@tonic-gate 	*hi_p = UINT64_MAX;
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 	return (DDI_SUCCESS);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate /*ARGSUSED*/
5950Sstevel@tonic-gate int
px_lib_iommu_getbypass(dev_info_t * dip,r_addr_t ra,io_attributes_t attr,io_addr_t * io_addr_p)5961617Sgovinda px_lib_iommu_getbypass(dev_info_t *dip, r_addr_t ra, io_attributes_t attr,
5971617Sgovinda     io_addr_t *io_addr_p)
5980Sstevel@tonic-gate {
5990Sstevel@tonic-gate 	uint64_t	ret;
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: dip 0x%p ra 0x%llx "
6029707SDaniel.Ice@Sun.COM 	    "attr 0x%llx\n", dip, ra, attr);
60311630Sandrew.rutz@sun.com 	/*
60412262SAlan.Adamson@Sun.COM 	 * If HV VPCI version is 2.0 and higher, pass BDF, phantom function,
60511630Sandrew.rutz@sun.com 	 * and relaxed ordering attributes. Otherwise, pass only read or write
60611630Sandrew.rutz@sun.com 	 * attribute.
60711630Sandrew.rutz@sun.com 	 */
60812262SAlan.Adamson@Sun.COM 	if ((px_vpci_maj_ver == PX_HSVC_MAJOR_VER_1) &&
60912262SAlan.Adamson@Sun.COM 	    (px_vpci_min_ver == PX_HSVC_MINOR_VER_0))
61011630Sandrew.rutz@sun.com 		attr &= PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE;
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	if ((ret = hvio_iommu_getbypass(DIP_TO_HANDLE(dip), ra,
6131617Sgovinda 	    attr, io_addr_p)) != H_EOK) {
6140Sstevel@tonic-gate 		DBG(DBG_LIB_DMA, dip,
6150Sstevel@tonic-gate 		    "hvio_iommu_getbypass failed, ret 0x%lx\n", ret);
6160Sstevel@tonic-gate 		return (ret == H_ENOTSUPPORTED ? DDI_ENOTSUP : DDI_FAILURE);
6170Sstevel@tonic-gate 	}
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: io_addr 0x%llx\n",
6200Sstevel@tonic-gate 	    *io_addr_p);
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	return (DDI_SUCCESS);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate 
6258691SLida.Horn@Sun.COM /*
6268691SLida.Horn@Sun.COM  * Returns any needed IO address bit(s) for relaxed ordering in IOMMU
6278691SLida.Horn@Sun.COM  * bypass mode.
6288691SLida.Horn@Sun.COM  */
6298691SLida.Horn@Sun.COM /* ARGSUSED */
6308691SLida.Horn@Sun.COM uint64_t
px_lib_ro_bypass(dev_info_t * dip,io_attributes_t attr,uint64_t ioaddr)6318691SLida.Horn@Sun.COM px_lib_ro_bypass(dev_info_t *dip, io_attributes_t attr, uint64_t ioaddr)
6328691SLida.Horn@Sun.COM {
6338691SLida.Horn@Sun.COM 	return (ioaddr);
6348691SLida.Horn@Sun.COM }
6358691SLida.Horn@Sun.COM 
6360Sstevel@tonic-gate /*ARGSUSED*/
6370Sstevel@tonic-gate int
px_lib_dma_sync(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,off_t off,size_t len,uint_t cache_flags)6380Sstevel@tonic-gate px_lib_dma_sync(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
6390Sstevel@tonic-gate 	off_t off, size_t len, uint_t cache_flags)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
6420Sstevel@tonic-gate 	uint64_t sync_dir;
6433107Saa72041 	size_t bytes_synced;
6443107Saa72041 	int end, idx;
6453107Saa72041 	off_t pg_off;
6463107Saa72041 	devhandle_t hdl = DIP_TO_HANDLE(dip); /* need to cache hdl */
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: dip 0x%p rdip 0x%p "
6490Sstevel@tonic-gate 	    "handle 0x%llx off 0x%x len 0x%x flags 0x%x\n",
6500Sstevel@tonic-gate 	    dip, rdip, handle, off, len, cache_flags);
6510Sstevel@tonic-gate 
652909Segillett 	if (!(mp->dmai_flags & PX_DMAI_FLAGS_INUSE)) {
65327Sjchu 		cmn_err(CE_WARN, "%s%d: Unbound dma handle %p.",
65427Sjchu 		    ddi_driver_name(rdip), ddi_get_instance(rdip), (void *)mp);
6550Sstevel@tonic-gate 		return (DDI_FAILURE);
6560Sstevel@tonic-gate 	}
6570Sstevel@tonic-gate 
658909Segillett 	if (mp->dmai_flags & PX_DMAI_FLAGS_NOSYNC)
6590Sstevel@tonic-gate 		return (DDI_SUCCESS);
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	if (!len)
6620Sstevel@tonic-gate 		len = mp->dmai_size;
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	if (mp->dmai_rflags & DDI_DMA_READ)
6650Sstevel@tonic-gate 		sync_dir = HVIO_DMA_SYNC_DIR_FROM_DEV;
6660Sstevel@tonic-gate 	else
6670Sstevel@tonic-gate 		sync_dir = HVIO_DMA_SYNC_DIR_TO_DEV;
6680Sstevel@tonic-gate 
6693107Saa72041 	off += mp->dmai_offset;
6703107Saa72041 	pg_off = off & MMU_PAGEOFFSET;
6713107Saa72041 
6723107Saa72041 	DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: page offset %x size %x\n",
6733107Saa72041 	    pg_off, len);
6743107Saa72041 
6753107Saa72041 	/* sync on page basis */
6763107Saa72041 	end = MMU_BTOPR(off + len - 1);
6773107Saa72041 	for (idx = MMU_BTOP(off); idx < end; idx++,
6783107Saa72041 	    len -= bytes_synced, pg_off = 0) {
67910271SJason.Beloro@Sun.COM 		size_t bytes_to_sync = bytes_to_sync =
68010271SJason.Beloro@Sun.COM 		    MIN(len, MMU_PAGESIZE - pg_off);
6813107Saa72041 
68210271SJason.Beloro@Sun.COM 		if (hvio_dma_sync(hdl, MMU_PTOB(PX_GET_MP_PFN(mp, idx)) +
68310271SJason.Beloro@Sun.COM 		    pg_off, bytes_to_sync, sync_dir, &bytes_synced) != H_EOK)
68410271SJason.Beloro@Sun.COM 			break;
6853107Saa72041 
6863107Saa72041 		DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: Called hvio_dma_sync "
6873107Saa72041 		    "ra = %p bytes to sync = %x bytes synced %x\n",
6883107Saa72041 		    MMU_PTOB(PX_GET_MP_PFN(mp, idx)) + pg_off, bytes_to_sync,
6893107Saa72041 		    bytes_synced);
6903107Saa72041 
6913107Saa72041 		if (bytes_to_sync != bytes_synced)
6923107Saa72041 			break;
6930Sstevel@tonic-gate 	}
6940Sstevel@tonic-gate 
6953107Saa72041 	return (len ? DDI_FAILURE : DDI_SUCCESS);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate  * MSIQ Functions:
7010Sstevel@tonic-gate  */
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate /*ARGSUSED*/
7040Sstevel@tonic-gate int
px_lib_msiq_init(dev_info_t * dip)7050Sstevel@tonic-gate px_lib_msiq_init(dev_info_t *dip)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate 	px_t		*px_p = DIP_TO_STATE(dip);
7080Sstevel@tonic-gate 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
7092755Segillett 	r_addr_t	ra;
7100Sstevel@tonic-gate 	size_t		msiq_size;
7110Sstevel@tonic-gate 	uint_t		rec_cnt;
7120Sstevel@tonic-gate 	int		i, err = DDI_SUCCESS;
7130Sstevel@tonic-gate 	uint64_t	ret;
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_init: dip 0x%p\n", dip);
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
7180Sstevel@tonic-gate 
7197403SAlan.Adamson@Sun.COM 	/* sun4v requires all EQ allocation to be on q size boundary */
7207403SAlan.Adamson@Sun.COM 	if ((msiq_state_p->msiq_buf_p = contig_mem_alloc_align(
7217403SAlan.Adamson@Sun.COM 	    msiq_state_p->msiq_cnt * msiq_size, msiq_size)) == NULL) {
7227403SAlan.Adamson@Sun.COM 		DBG(DBG_LIB_MSIQ, dip,
7237403SAlan.Adamson@Sun.COM 		    "px_lib_msiq_init: Contig alloc failed\n");
7247403SAlan.Adamson@Sun.COM 
7257403SAlan.Adamson@Sun.COM 		return (DDI_FAILURE);
7267403SAlan.Adamson@Sun.COM 	}
7277403SAlan.Adamson@Sun.COM 
7280Sstevel@tonic-gate 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
7297403SAlan.Adamson@Sun.COM 		msiq_state_p->msiq_p[i].msiq_base_p = (msiqhead_t *)
7307403SAlan.Adamson@Sun.COM 		    ((caddr_t)msiq_state_p->msiq_buf_p + (i * msiq_size));
7317403SAlan.Adamson@Sun.COM 
7322755Segillett 		ra = (r_addr_t)va_to_pa((caddr_t)msiq_state_p->msiq_buf_p +
7332755Segillett 		    (i * msiq_size));
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate 		if ((ret = hvio_msiq_conf(DIP_TO_HANDLE(dip),
7360Sstevel@tonic-gate 		    (i + msiq_state_p->msiq_1st_msiq_id),
7370Sstevel@tonic-gate 		    ra, msiq_state_p->msiq_rec_cnt)) != H_EOK) {
7380Sstevel@tonic-gate 			DBG(DBG_LIB_MSIQ, dip,
7390Sstevel@tonic-gate 			    "hvio_msiq_conf failed, ret 0x%lx\n", ret);
7400Sstevel@tonic-gate 			err = DDI_FAILURE;
7410Sstevel@tonic-gate 			break;
7420Sstevel@tonic-gate 		}
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 		if ((err = px_lib_msiq_info(dip,
7450Sstevel@tonic-gate 		    (i + msiq_state_p->msiq_1st_msiq_id),
7460Sstevel@tonic-gate 		    &ra, &rec_cnt)) != DDI_SUCCESS) {
7470Sstevel@tonic-gate 			DBG(DBG_LIB_MSIQ, dip,
7480Sstevel@tonic-gate 			    "px_lib_msiq_info failed, ret 0x%x\n", err);
7490Sstevel@tonic-gate 			err = DDI_FAILURE;
7500Sstevel@tonic-gate 			break;
7510Sstevel@tonic-gate 		}
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
7540Sstevel@tonic-gate 		    "px_lib_msiq_init: ra 0x%p rec_cnt 0x%x\n", ra, rec_cnt);
7550Sstevel@tonic-gate 	}
7560Sstevel@tonic-gate 
7570Sstevel@tonic-gate 	return (err);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate /*ARGSUSED*/
7610Sstevel@tonic-gate int
px_lib_msiq_fini(dev_info_t * dip)7620Sstevel@tonic-gate px_lib_msiq_fini(dev_info_t *dip)
7630Sstevel@tonic-gate {
7647403SAlan.Adamson@Sun.COM 	px_t		*px_p = DIP_TO_STATE(dip);
7657403SAlan.Adamson@Sun.COM 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
7667403SAlan.Adamson@Sun.COM 	size_t		msiq_size;
7677403SAlan.Adamson@Sun.COM 
7680Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_fini: dip 0x%p\n", dip);
7697403SAlan.Adamson@Sun.COM 	msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
7707403SAlan.Adamson@Sun.COM 
7717403SAlan.Adamson@Sun.COM 	if (msiq_state_p->msiq_buf_p != NULL)
7727403SAlan.Adamson@Sun.COM 		contig_mem_free(msiq_state_p->msiq_buf_p,
7737403SAlan.Adamson@Sun.COM 		    msiq_state_p->msiq_cnt * msiq_size);
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 	return (DDI_SUCCESS);
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate /*ARGSUSED*/
7790Sstevel@tonic-gate int
px_lib_msiq_info(dev_info_t * dip,msiqid_t msiq_id,r_addr_t * ra_p,uint_t * msiq_rec_cnt_p)7800Sstevel@tonic-gate px_lib_msiq_info(dev_info_t *dip, msiqid_t msiq_id, r_addr_t *ra_p,
7810Sstevel@tonic-gate     uint_t *msiq_rec_cnt_p)
7820Sstevel@tonic-gate {
7830Sstevel@tonic-gate 	uint64_t	ret;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: dip 0x%p msiq_id 0x%x\n",
7860Sstevel@tonic-gate 	    dip, msiq_id);
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 	if ((ret = hvio_msiq_info(DIP_TO_HANDLE(dip),
7890Sstevel@tonic-gate 	    msiq_id, ra_p, msiq_rec_cnt_p)) != H_EOK) {
7900Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
7910Sstevel@tonic-gate 		    "hvio_msiq_info failed, ret 0x%lx\n", ret);
7920Sstevel@tonic-gate 		return (DDI_FAILURE);
7930Sstevel@tonic-gate 	}
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: ra_p 0x%p msiq_rec_cnt 0x%x\n",
7960Sstevel@tonic-gate 	    ra_p, *msiq_rec_cnt_p);
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	return (DDI_SUCCESS);
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate /*ARGSUSED*/
8020Sstevel@tonic-gate int
px_lib_msiq_getvalid(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_valid_state_t * msiq_valid_state)8030Sstevel@tonic-gate px_lib_msiq_getvalid(dev_info_t *dip, msiqid_t msiq_id,
8040Sstevel@tonic-gate     pci_msiq_valid_state_t *msiq_valid_state)
8050Sstevel@tonic-gate {
8060Sstevel@tonic-gate 	uint64_t	ret;
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: dip 0x%p msiq_id 0x%x\n",
8090Sstevel@tonic-gate 	    dip, msiq_id);
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if ((ret = hvio_msiq_getvalid(DIP_TO_HANDLE(dip),
8120Sstevel@tonic-gate 	    msiq_id, msiq_valid_state)) != H_EOK) {
8130Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
8140Sstevel@tonic-gate 		    "hvio_msiq_getvalid failed, ret 0x%lx\n", ret);
8150Sstevel@tonic-gate 		return (DDI_FAILURE);
8160Sstevel@tonic-gate 	}
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: msiq_valid_state 0x%x\n",
8190Sstevel@tonic-gate 	    *msiq_valid_state);
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 	return (DDI_SUCCESS);
8220Sstevel@tonic-gate }
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate /*ARGSUSED*/
8250Sstevel@tonic-gate int
px_lib_msiq_setvalid(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_valid_state_t msiq_valid_state)8260Sstevel@tonic-gate px_lib_msiq_setvalid(dev_info_t *dip, msiqid_t msiq_id,
8270Sstevel@tonic-gate     pci_msiq_valid_state_t msiq_valid_state)
8280Sstevel@tonic-gate {
8290Sstevel@tonic-gate 	uint64_t	ret;
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setvalid: dip 0x%p msiq_id 0x%x "
8320Sstevel@tonic-gate 	    "msiq_valid_state 0x%x\n", dip, msiq_id, msiq_valid_state);
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	if ((ret = hvio_msiq_setvalid(DIP_TO_HANDLE(dip),
8350Sstevel@tonic-gate 	    msiq_id, msiq_valid_state)) != H_EOK) {
8360Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
8370Sstevel@tonic-gate 		    "hvio_msiq_setvalid failed, ret 0x%lx\n", ret);
8380Sstevel@tonic-gate 		return (DDI_FAILURE);
8390Sstevel@tonic-gate 	}
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	return (DDI_SUCCESS);
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate /*ARGSUSED*/
8450Sstevel@tonic-gate int
px_lib_msiq_getstate(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_state_t * msiq_state)8460Sstevel@tonic-gate px_lib_msiq_getstate(dev_info_t *dip, msiqid_t msiq_id,
8470Sstevel@tonic-gate     pci_msiq_state_t *msiq_state)
8480Sstevel@tonic-gate {
8490Sstevel@tonic-gate 	uint64_t	ret;
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: dip 0x%p msiq_id 0x%x\n",
8520Sstevel@tonic-gate 	    dip, msiq_id);
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	if ((ret = hvio_msiq_getstate(DIP_TO_HANDLE(dip),
8550Sstevel@tonic-gate 	    msiq_id, msiq_state)) != H_EOK) {
8560Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
8570Sstevel@tonic-gate 		    "hvio_msiq_getstate failed, ret 0x%lx\n", ret);
8580Sstevel@tonic-gate 		return (DDI_FAILURE);
8590Sstevel@tonic-gate 	}
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: msiq_state 0x%x\n",
8620Sstevel@tonic-gate 	    *msiq_state);
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 	return (DDI_SUCCESS);
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate /*ARGSUSED*/
8680Sstevel@tonic-gate int
px_lib_msiq_setstate(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_state_t msiq_state)8690Sstevel@tonic-gate px_lib_msiq_setstate(dev_info_t *dip, msiqid_t msiq_id,
8700Sstevel@tonic-gate     pci_msiq_state_t msiq_state)
8710Sstevel@tonic-gate {
8720Sstevel@tonic-gate 	uint64_t	ret;
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setstate: dip 0x%p msiq_id 0x%x "
8750Sstevel@tonic-gate 	    "msiq_state 0x%x\n", dip, msiq_id, msiq_state);
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate 	if ((ret = hvio_msiq_setstate(DIP_TO_HANDLE(dip),
8780Sstevel@tonic-gate 	    msiq_id, msiq_state)) != H_EOK) {
8790Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
8800Sstevel@tonic-gate 		    "hvio_msiq_setstate failed, ret 0x%lx\n", ret);
8810Sstevel@tonic-gate 		return (DDI_FAILURE);
8820Sstevel@tonic-gate 	}
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate 	return (DDI_SUCCESS);
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate 
8870Sstevel@tonic-gate /*ARGSUSED*/
8880Sstevel@tonic-gate int
px_lib_msiq_gethead(dev_info_t * dip,msiqid_t msiq_id,msiqhead_t * msiq_head_p)8890Sstevel@tonic-gate px_lib_msiq_gethead(dev_info_t *dip, msiqid_t msiq_id,
8900Sstevel@tonic-gate     msiqhead_t *msiq_head_p)
8910Sstevel@tonic-gate {
8920Sstevel@tonic-gate 	uint64_t	ret;
8930Sstevel@tonic-gate 
8940Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gethead: dip 0x%p msiq_id 0x%x\n",
8950Sstevel@tonic-gate 	    dip, msiq_id);
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	if ((ret = hvio_msiq_gethead(DIP_TO_HANDLE(dip),
8980Sstevel@tonic-gate 	    msiq_id, msiq_head_p)) != H_EOK) {
8990Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
9000Sstevel@tonic-gate 		    "hvio_msiq_gethead failed, ret 0x%lx\n", ret);
9010Sstevel@tonic-gate 		return (DDI_FAILURE);
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 	*msiq_head_p =  (*msiq_head_p / sizeof (msiq_rec_t));
9050Sstevel@tonic-gate 
9060Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_msiq_gethead: msiq_head 0x%x\n",
9070Sstevel@tonic-gate 	    *msiq_head_p);
9080Sstevel@tonic-gate 
9090Sstevel@tonic-gate 	return (DDI_SUCCESS);
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate /*ARGSUSED*/
9130Sstevel@tonic-gate int
px_lib_msiq_sethead(dev_info_t * dip,msiqid_t msiq_id,msiqhead_t msiq_head)9140Sstevel@tonic-gate px_lib_msiq_sethead(dev_info_t *dip, msiqid_t msiq_id,
9150Sstevel@tonic-gate     msiqhead_t msiq_head)
9160Sstevel@tonic-gate {
9170Sstevel@tonic-gate 	uint64_t	ret;
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_sethead: dip 0x%p msiq_id 0x%x "
9200Sstevel@tonic-gate 	    "msiq_head 0x%x\n", dip, msiq_id, msiq_head);
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	if ((ret = hvio_msiq_sethead(DIP_TO_HANDLE(dip),
9230Sstevel@tonic-gate 	    msiq_id, msiq_head * sizeof (msiq_rec_t))) != H_EOK) {
9240Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
9250Sstevel@tonic-gate 		    "hvio_msiq_sethead failed, ret 0x%lx\n", ret);
9260Sstevel@tonic-gate 		return (DDI_FAILURE);
9270Sstevel@tonic-gate 	}
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate 	return (DDI_SUCCESS);
9300Sstevel@tonic-gate }
9310Sstevel@tonic-gate 
9320Sstevel@tonic-gate /*ARGSUSED*/
9330Sstevel@tonic-gate int
px_lib_msiq_gettail(dev_info_t * dip,msiqid_t msiq_id,msiqtail_t * msiq_tail_p)9340Sstevel@tonic-gate px_lib_msiq_gettail(dev_info_t *dip, msiqid_t msiq_id,
9350Sstevel@tonic-gate     msiqtail_t *msiq_tail_p)
9360Sstevel@tonic-gate {
9370Sstevel@tonic-gate 	uint64_t	ret;
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: dip 0x%p msiq_id 0x%x\n",
9400Sstevel@tonic-gate 	    dip, msiq_id);
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 	if ((ret = hvio_msiq_gettail(DIP_TO_HANDLE(dip),
9430Sstevel@tonic-gate 	    msiq_id, msiq_tail_p)) != H_EOK) {
9440Sstevel@tonic-gate 		DBG(DBG_LIB_MSIQ, dip,
9450Sstevel@tonic-gate 		    "hvio_msiq_gettail failed, ret 0x%lx\n", ret);
9460Sstevel@tonic-gate 		return (DDI_FAILURE);
9470Sstevel@tonic-gate 	}
9480Sstevel@tonic-gate 
9490Sstevel@tonic-gate 	*msiq_tail_p =  (*msiq_tail_p / sizeof (msiq_rec_t));
9500Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: msiq_tail 0x%x\n",
9510Sstevel@tonic-gate 	    *msiq_tail_p);
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate 	return (DDI_SUCCESS);
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate /*ARGSUSED*/
9570Sstevel@tonic-gate void
px_lib_get_msiq_rec(dev_info_t * dip,msiqhead_t * msiq_head_p,msiq_rec_t * msiq_rec_p)9582588Segillett px_lib_get_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p,
9592588Segillett     msiq_rec_t *msiq_rec_p)
9600Sstevel@tonic-gate {
9612588Segillett 	msiq_rec_t	*curr_msiq_rec_p = (msiq_rec_t *)msiq_head_p;
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: dip 0x%p\n", dip);
9640Sstevel@tonic-gate 
9652973Sgovinda 	if (!curr_msiq_rec_p->msiq_rec_type) {
9662973Sgovinda 		/* Set msiq_rec_type to zero */
9672973Sgovinda 		msiq_rec_p->msiq_rec_type = 0;
9682973Sgovinda 
9690Sstevel@tonic-gate 		return;
9702973Sgovinda 	}
9710Sstevel@tonic-gate 
9720Sstevel@tonic-gate 	*msiq_rec_p = *curr_msiq_rec_p;
9732973Sgovinda }
9742973Sgovinda 
9752973Sgovinda /*ARGSUSED*/
9762973Sgovinda void
px_lib_clr_msiq_rec(dev_info_t * dip,msiqhead_t * msiq_head_p)9772973Sgovinda px_lib_clr_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p)
9782973Sgovinda {
9792973Sgovinda 	msiq_rec_t	*curr_msiq_rec_p = (msiq_rec_t *)msiq_head_p;
9802973Sgovinda 
9812973Sgovinda 	DBG(DBG_LIB_MSIQ, dip, "px_lib_clr_msiq_rec: dip 0x%p\n", dip);
9820Sstevel@tonic-gate 
983287Smg140465 	/* Zero out msiq_rec_type field */
984287Smg140465 	curr_msiq_rec_p->msiq_rec_type  = 0;
9850Sstevel@tonic-gate }
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate /*
9880Sstevel@tonic-gate  * MSI Functions:
9890Sstevel@tonic-gate  */
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate /*ARGSUSED*/
9920Sstevel@tonic-gate int
px_lib_msi_init(dev_info_t * dip)9930Sstevel@tonic-gate px_lib_msi_init(dev_info_t *dip)
9940Sstevel@tonic-gate {
9950Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_init: dip 0x%p\n", dip);
9960Sstevel@tonic-gate 
9970Sstevel@tonic-gate 	/* Noop */
9980Sstevel@tonic-gate 	return (DDI_SUCCESS);
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate /*ARGSUSED*/
10020Sstevel@tonic-gate int
px_lib_msi_getmsiq(dev_info_t * dip,msinum_t msi_num,msiqid_t * msiq_id)10030Sstevel@tonic-gate px_lib_msi_getmsiq(dev_info_t *dip, msinum_t msi_num,
10040Sstevel@tonic-gate     msiqid_t *msiq_id)
10050Sstevel@tonic-gate {
10060Sstevel@tonic-gate 	uint64_t	ret;
10070Sstevel@tonic-gate 
10080Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: dip 0x%p msi_num 0x%x\n",
10090Sstevel@tonic-gate 	    dip, msi_num);
10100Sstevel@tonic-gate 
10110Sstevel@tonic-gate 	if ((ret = hvio_msi_getmsiq(DIP_TO_HANDLE(dip),
10120Sstevel@tonic-gate 	    msi_num, msiq_id)) != H_EOK) {
10130Sstevel@tonic-gate 		DBG(DBG_LIB_MSI, dip,
10140Sstevel@tonic-gate 		    "hvio_msi_getmsiq failed, ret 0x%lx\n", ret);
10150Sstevel@tonic-gate 		return (DDI_FAILURE);
10160Sstevel@tonic-gate 	}
10170Sstevel@tonic-gate 
10180Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: msiq_id 0x%x\n",
10190Sstevel@tonic-gate 	    *msiq_id);
10200Sstevel@tonic-gate 
10210Sstevel@tonic-gate 	return (DDI_SUCCESS);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate 
10240Sstevel@tonic-gate /*ARGSUSED*/
10250Sstevel@tonic-gate int
px_lib_msi_setmsiq(dev_info_t * dip,msinum_t msi_num,msiqid_t msiq_id,msi_type_t msitype)10260Sstevel@tonic-gate px_lib_msi_setmsiq(dev_info_t *dip, msinum_t msi_num,
10270Sstevel@tonic-gate     msiqid_t msiq_id, msi_type_t msitype)
10280Sstevel@tonic-gate {
10290Sstevel@tonic-gate 	uint64_t	ret;
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_setmsiq: dip 0x%p msi_num 0x%x "
10320Sstevel@tonic-gate 	    "msq_id 0x%x\n", dip, msi_num, msiq_id);
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	if ((ret = hvio_msi_setmsiq(DIP_TO_HANDLE(dip),
10350Sstevel@tonic-gate 	    msi_num, msiq_id, msitype)) != H_EOK) {
10360Sstevel@tonic-gate 		DBG(DBG_LIB_MSI, dip,
10370Sstevel@tonic-gate 		    "hvio_msi_setmsiq failed, ret 0x%lx\n", ret);
10380Sstevel@tonic-gate 		return (DDI_FAILURE);
10390Sstevel@tonic-gate 	}
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate 	return (DDI_SUCCESS);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate 
10440Sstevel@tonic-gate /*ARGSUSED*/
10450Sstevel@tonic-gate int
px_lib_msi_getvalid(dev_info_t * dip,msinum_t msi_num,pci_msi_valid_state_t * msi_valid_state)10460Sstevel@tonic-gate px_lib_msi_getvalid(dev_info_t *dip, msinum_t msi_num,
10470Sstevel@tonic-gate     pci_msi_valid_state_t *msi_valid_state)
10480Sstevel@tonic-gate {
10490Sstevel@tonic-gate 	uint64_t	ret;
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: dip 0x%p msi_num 0x%x\n",
10520Sstevel@tonic-gate 	    dip, msi_num);
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 	if ((ret = hvio_msi_getvalid(DIP_TO_HANDLE(dip),
10550Sstevel@tonic-gate 	    msi_num, msi_valid_state)) != H_EOK) {
10560Sstevel@tonic-gate 		DBG(DBG_LIB_MSI, dip,
10570Sstevel@tonic-gate 		    "hvio_msi_getvalid failed, ret 0x%lx\n", ret);
10580Sstevel@tonic-gate 		return (DDI_FAILURE);
10590Sstevel@tonic-gate 	}
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: msiq_id 0x%x\n",
10620Sstevel@tonic-gate 	    *msi_valid_state);
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate 	return (DDI_SUCCESS);
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate /*ARGSUSED*/
10680Sstevel@tonic-gate int
px_lib_msi_setvalid(dev_info_t * dip,msinum_t msi_num,pci_msi_valid_state_t msi_valid_state)10690Sstevel@tonic-gate px_lib_msi_setvalid(dev_info_t *dip, msinum_t msi_num,
10700Sstevel@tonic-gate     pci_msi_valid_state_t msi_valid_state)
10710Sstevel@tonic-gate {
10720Sstevel@tonic-gate 	uint64_t	ret;
10730Sstevel@tonic-gate 
10740Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_setvalid: dip 0x%p msi_num 0x%x "
10750Sstevel@tonic-gate 	    "msi_valid_state 0x%x\n", dip, msi_num, msi_valid_state);
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	if ((ret = hvio_msi_setvalid(DIP_TO_HANDLE(dip),
10780Sstevel@tonic-gate 	    msi_num, msi_valid_state)) != H_EOK) {
10790Sstevel@tonic-gate 		DBG(DBG_LIB_MSI, dip,
10800Sstevel@tonic-gate 		    "hvio_msi_setvalid failed, ret 0x%lx\n", ret);
10810Sstevel@tonic-gate 		return (DDI_FAILURE);
10820Sstevel@tonic-gate 	}
10830Sstevel@tonic-gate 
10840Sstevel@tonic-gate 	return (DDI_SUCCESS);
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate /*ARGSUSED*/
10880Sstevel@tonic-gate int
px_lib_msi_getstate(dev_info_t * dip,msinum_t msi_num,pci_msi_state_t * msi_state)10890Sstevel@tonic-gate px_lib_msi_getstate(dev_info_t *dip, msinum_t msi_num,
10900Sstevel@tonic-gate     pci_msi_state_t *msi_state)
10910Sstevel@tonic-gate {
10920Sstevel@tonic-gate 	uint64_t	ret;
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: dip 0x%p msi_num 0x%x\n",
10950Sstevel@tonic-gate 	    dip, msi_num);
10960Sstevel@tonic-gate 
10970Sstevel@tonic-gate 	if ((ret = hvio_msi_getstate(DIP_TO_HANDLE(dip),
10980Sstevel@tonic-gate 	    msi_num, msi_state)) != H_EOK) {
10990Sstevel@tonic-gate 		DBG(DBG_LIB_MSI, dip,
11000Sstevel@tonic-gate 		    "hvio_msi_getstate failed, ret 0x%lx\n", ret);
11010Sstevel@tonic-gate 		return (DDI_FAILURE);
11020Sstevel@tonic-gate 	}
11030Sstevel@tonic-gate 
11040Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: msi_state 0x%x\n",
11050Sstevel@tonic-gate 	    *msi_state);
11060Sstevel@tonic-gate 
11070Sstevel@tonic-gate 	return (DDI_SUCCESS);
11080Sstevel@tonic-gate }
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate /*ARGSUSED*/
11110Sstevel@tonic-gate int
px_lib_msi_setstate(dev_info_t * dip,msinum_t msi_num,pci_msi_state_t msi_state)11120Sstevel@tonic-gate px_lib_msi_setstate(dev_info_t *dip, msinum_t msi_num,
11130Sstevel@tonic-gate     pci_msi_state_t msi_state)
11140Sstevel@tonic-gate {
11150Sstevel@tonic-gate 	uint64_t	ret;
11160Sstevel@tonic-gate 
11170Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_setstate: dip 0x%p msi_num 0x%x "
11180Sstevel@tonic-gate 	    "msi_state 0x%x\n", dip, msi_num, msi_state);
11190Sstevel@tonic-gate 
11200Sstevel@tonic-gate 	if ((ret = hvio_msi_setstate(DIP_TO_HANDLE(dip),
11210Sstevel@tonic-gate 	    msi_num, msi_state)) != H_EOK) {
11220Sstevel@tonic-gate 		DBG(DBG_LIB_MSI, dip,
11230Sstevel@tonic-gate 		    "hvio_msi_setstate failed, ret 0x%lx\n", ret);
11240Sstevel@tonic-gate 		return (DDI_FAILURE);
11250Sstevel@tonic-gate 	}
11260Sstevel@tonic-gate 
11270Sstevel@tonic-gate 	return (DDI_SUCCESS);
11280Sstevel@tonic-gate }
11290Sstevel@tonic-gate 
11300Sstevel@tonic-gate /*
11310Sstevel@tonic-gate  * MSG Functions:
11320Sstevel@tonic-gate  */
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate /*ARGSUSED*/
11350Sstevel@tonic-gate int
px_lib_msg_getmsiq(dev_info_t * dip,pcie_msg_type_t msg_type,msiqid_t * msiq_id)11360Sstevel@tonic-gate px_lib_msg_getmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
11370Sstevel@tonic-gate     msiqid_t *msiq_id)
11380Sstevel@tonic-gate {
11390Sstevel@tonic-gate 	uint64_t	ret;
11400Sstevel@tonic-gate 
11410Sstevel@tonic-gate 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_getmsiq: dip 0x%p msg_type 0x%x\n",
11420Sstevel@tonic-gate 	    dip, msg_type);
11430Sstevel@tonic-gate 
11440Sstevel@tonic-gate 	if ((ret = hvio_msg_getmsiq(DIP_TO_HANDLE(dip),
11450Sstevel@tonic-gate 	    msg_type, msiq_id)) != H_EOK) {
11460Sstevel@tonic-gate 		DBG(DBG_LIB_MSG, dip,
11470Sstevel@tonic-gate 		    "hvio_msg_getmsiq failed, ret 0x%lx\n", ret);
11480Sstevel@tonic-gate 		return (DDI_FAILURE);
11490Sstevel@tonic-gate 	}
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msg_getmsiq: msiq_id 0x%x\n",
11520Sstevel@tonic-gate 	    *msiq_id);
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 	return (DDI_SUCCESS);
11550Sstevel@tonic-gate }
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate /*ARGSUSED*/
11580Sstevel@tonic-gate int
px_lib_msg_setmsiq(dev_info_t * dip,pcie_msg_type_t msg_type,msiqid_t msiq_id)11590Sstevel@tonic-gate px_lib_msg_setmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
11600Sstevel@tonic-gate     msiqid_t msiq_id)
11610Sstevel@tonic-gate {
11620Sstevel@tonic-gate 	uint64_t	ret;
11630Sstevel@tonic-gate 
11640Sstevel@tonic-gate 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_setmsiq: dip 0x%p msg_type 0x%x "
11650Sstevel@tonic-gate 	    "msq_id 0x%x\n", dip, msg_type, msiq_id);
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 	if ((ret = hvio_msg_setmsiq(DIP_TO_HANDLE(dip),
11680Sstevel@tonic-gate 	    msg_type, msiq_id)) != H_EOK) {
11690Sstevel@tonic-gate 		DBG(DBG_LIB_MSG, dip,
11700Sstevel@tonic-gate 		    "hvio_msg_setmsiq failed, ret 0x%lx\n", ret);
11710Sstevel@tonic-gate 		return (DDI_FAILURE);
11720Sstevel@tonic-gate 	}
11730Sstevel@tonic-gate 
11740Sstevel@tonic-gate 	return (DDI_SUCCESS);
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate 
11770Sstevel@tonic-gate /*ARGSUSED*/
11780Sstevel@tonic-gate int
px_lib_msg_getvalid(dev_info_t * dip,pcie_msg_type_t msg_type,pcie_msg_valid_state_t * msg_valid_state)11790Sstevel@tonic-gate px_lib_msg_getvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
11800Sstevel@tonic-gate     pcie_msg_valid_state_t *msg_valid_state)
11810Sstevel@tonic-gate {
11820Sstevel@tonic-gate 	uint64_t	ret;
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_getvalid: dip 0x%p msg_type 0x%x\n",
11850Sstevel@tonic-gate 	    dip, msg_type);
11860Sstevel@tonic-gate 
11870Sstevel@tonic-gate 	if ((ret = hvio_msg_getvalid(DIP_TO_HANDLE(dip), msg_type,
11880Sstevel@tonic-gate 	    msg_valid_state)) != H_EOK) {
11890Sstevel@tonic-gate 		DBG(DBG_LIB_MSG, dip,
11900Sstevel@tonic-gate 		    "hvio_msg_getvalid failed, ret 0x%lx\n", ret);
11910Sstevel@tonic-gate 		return (DDI_FAILURE);
11920Sstevel@tonic-gate 	}
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 	DBG(DBG_LIB_MSI, dip, "px_lib_msg_getvalid: msg_valid_state 0x%x\n",
11950Sstevel@tonic-gate 	    *msg_valid_state);
11960Sstevel@tonic-gate 
11970Sstevel@tonic-gate 	return (DDI_SUCCESS);
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate /*ARGSUSED*/
12010Sstevel@tonic-gate int
px_lib_msg_setvalid(dev_info_t * dip,pcie_msg_type_t msg_type,pcie_msg_valid_state_t msg_valid_state)12020Sstevel@tonic-gate px_lib_msg_setvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
12030Sstevel@tonic-gate     pcie_msg_valid_state_t msg_valid_state)
12040Sstevel@tonic-gate {
12050Sstevel@tonic-gate 	uint64_t	ret;
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_setvalid: dip 0x%p msg_type 0x%x "
12080Sstevel@tonic-gate 	    "msg_valid_state 0x%x\n", dip, msg_type, msg_valid_state);
12090Sstevel@tonic-gate 
12100Sstevel@tonic-gate 	if ((ret = hvio_msg_setvalid(DIP_TO_HANDLE(dip), msg_type,
12110Sstevel@tonic-gate 	    msg_valid_state)) != H_EOK) {
12120Sstevel@tonic-gate 		DBG(DBG_LIB_MSG, dip,
12130Sstevel@tonic-gate 		    "hvio_msg_setvalid failed, ret 0x%lx\n", ret);
12140Sstevel@tonic-gate 		return (DDI_FAILURE);
12150Sstevel@tonic-gate 	}
12160Sstevel@tonic-gate 
12170Sstevel@tonic-gate 	return (DDI_SUCCESS);
12180Sstevel@tonic-gate }
12190Sstevel@tonic-gate 
12200Sstevel@tonic-gate /*
12210Sstevel@tonic-gate  * Suspend/Resume Functions:
12220Sstevel@tonic-gate  * Currently unsupported by hypervisor and all functions are noops.
12230Sstevel@tonic-gate  */
12240Sstevel@tonic-gate /*ARGSUSED*/
12250Sstevel@tonic-gate int
px_lib_suspend(dev_info_t * dip)12260Sstevel@tonic-gate px_lib_suspend(dev_info_t *dip)
12270Sstevel@tonic-gate {
12280Sstevel@tonic-gate 	DBG(DBG_ATTACH, dip, "px_lib_suspend: Not supported\n");
12290Sstevel@tonic-gate 
12300Sstevel@tonic-gate 	/* Not supported */
12310Sstevel@tonic-gate 	return (DDI_FAILURE);
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate 
12340Sstevel@tonic-gate /*ARGSUSED*/
12350Sstevel@tonic-gate void
px_lib_resume(dev_info_t * dip)12360Sstevel@tonic-gate px_lib_resume(dev_info_t *dip)
12370Sstevel@tonic-gate {
12380Sstevel@tonic-gate 	DBG(DBG_ATTACH, dip, "px_lib_resume: Not supported\n");
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	/* Noop */
12410Sstevel@tonic-gate }
12420Sstevel@tonic-gate 
12430Sstevel@tonic-gate /*
12440Sstevel@tonic-gate  * Misc Functions:
12450Sstevel@tonic-gate  * Currently unsupported by hypervisor and all functions are noops.
12460Sstevel@tonic-gate  */
12470Sstevel@tonic-gate /*ARGSUSED*/
12480Sstevel@tonic-gate static int
px_lib_config_get(dev_info_t * dip,pci_device_t bdf,pci_config_offset_t off,uint8_t size,pci_cfg_data_t * data_p)12490Sstevel@tonic-gate px_lib_config_get(dev_info_t *dip, pci_device_t bdf, pci_config_offset_t off,
12500Sstevel@tonic-gate     uint8_t size, pci_cfg_data_t *data_p)
12510Sstevel@tonic-gate {
12520Sstevel@tonic-gate 	uint64_t	ret;
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate 	DBG(DBG_LIB_CFG, dip, "px_lib_config_get: dip 0x%p, bdf 0x%llx "
12550Sstevel@tonic-gate 	    "off 0x%x size 0x%x\n", dip, bdf, off, size);
12560Sstevel@tonic-gate 
12570Sstevel@tonic-gate 	if ((ret = hvio_config_get(DIP_TO_HANDLE(dip), bdf, off,
12580Sstevel@tonic-gate 	    size, data_p)) != H_EOK) {
12590Sstevel@tonic-gate 		DBG(DBG_LIB_CFG, dip,
12600Sstevel@tonic-gate 		    "hvio_config_get failed, ret 0x%lx\n", ret);
12610Sstevel@tonic-gate 		return (DDI_FAILURE);
12620Sstevel@tonic-gate 	}
12630Sstevel@tonic-gate 	DBG(DBG_LIB_CFG, dip, "px_config_get: data 0x%x\n", data_p->dw);
12640Sstevel@tonic-gate 
12650Sstevel@tonic-gate 	return (DDI_SUCCESS);
12660Sstevel@tonic-gate }
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate /*ARGSUSED*/
12690Sstevel@tonic-gate static int
px_lib_config_put(dev_info_t * dip,pci_device_t bdf,pci_config_offset_t off,uint8_t size,pci_cfg_data_t data)12700Sstevel@tonic-gate px_lib_config_put(dev_info_t *dip, pci_device_t bdf, pci_config_offset_t off,
12710Sstevel@tonic-gate     uint8_t size, pci_cfg_data_t data)
12720Sstevel@tonic-gate {
12730Sstevel@tonic-gate 	uint64_t	ret;
12740Sstevel@tonic-gate 
12750Sstevel@tonic-gate 	DBG(DBG_LIB_CFG, dip, "px_lib_config_put: dip 0x%p, bdf 0x%llx "
12760Sstevel@tonic-gate 	    "off 0x%x size 0x%x data 0x%llx\n", dip, bdf, off, size, data.qw);
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 	if ((ret = hvio_config_put(DIP_TO_HANDLE(dip), bdf, off,
12790Sstevel@tonic-gate 	    size, data)) != H_EOK) {
12800Sstevel@tonic-gate 		DBG(DBG_LIB_CFG, dip,
12810Sstevel@tonic-gate 		    "hvio_config_put failed, ret 0x%lx\n", ret);
12820Sstevel@tonic-gate 		return (DDI_FAILURE);
12830Sstevel@tonic-gate 	}
12840Sstevel@tonic-gate 
12850Sstevel@tonic-gate 	return (DDI_SUCCESS);
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate 
12880Sstevel@tonic-gate static uint32_t
px_pci_config_get(ddi_acc_impl_t * handle,uint32_t * addr,int size)12890Sstevel@tonic-gate px_pci_config_get(ddi_acc_impl_t *handle, uint32_t *addr, int size)
12900Sstevel@tonic-gate {
12916313Skrishnae 	px_config_acc_pvt_t *px_pvt = (px_config_acc_pvt_t *)
12926313Skrishnae 	    handle->ahi_common.ah_bus_private;
129311596SJason.Beloro@Sun.COM 	pcie_bus_t *busp = NULL;
129411596SJason.Beloro@Sun.COM 	dev_info_t *cdip = NULL;
12950Sstevel@tonic-gate 	uint32_t pci_dev_addr = px_pvt->raddr;
12960Sstevel@tonic-gate 	uint32_t vaddr = px_pvt->vaddr;
1297671Skrishnae 	uint16_t off = (uint16_t)(uintptr_t)(addr - vaddr) & 0xfff;
129810595SShesha.Sreenivasamurthy@Sun.COM 	uint64_t rdata = 0;
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate 	if (px_lib_config_get(px_pvt->dip, pci_dev_addr, off,
13016313Skrishnae 	    size, (pci_cfg_data_t *)&rdata) != DDI_SUCCESS)
13020Sstevel@tonic-gate 		/* XXX update error kstats */
13030Sstevel@tonic-gate 		return (0xffffffff);
130411596SJason.Beloro@Sun.COM 
130511596SJason.Beloro@Sun.COM 	if (cdip = pcie_find_dip_by_bdf(px_pvt->dip, pci_dev_addr >> 8))
130611596SJason.Beloro@Sun.COM 		busp = PCIE_DIP2BUS(cdip);
130711596SJason.Beloro@Sun.COM 	/*
130811596SJason.Beloro@Sun.COM 	 * This can be called early, before busp or busp->bus_dom has
130911596SJason.Beloro@Sun.COM 	 * been initialized, so check both before invoking
131011596SJason.Beloro@Sun.COM 	 * PCIE_IS_ASSIGNED.
131111596SJason.Beloro@Sun.COM 	 */
131211596SJason.Beloro@Sun.COM 	if (busp && PCIE_BUS2DOM(busp) && PCIE_IS_ASSIGNED(busp)) {
131311596SJason.Beloro@Sun.COM 		if (off == PCI_CONF_VENID && size == 2)
131411596SJason.Beloro@Sun.COM 			rdata = busp->bus_dev_ven_id & 0xffff;
131511596SJason.Beloro@Sun.COM 		else if (off == PCI_CONF_DEVID && size == 2)
131611596SJason.Beloro@Sun.COM 			rdata = busp->bus_dev_ven_id >> 16;
131711596SJason.Beloro@Sun.COM 		else if (off == PCI_CONF_VENID && size == 4)
131811596SJason.Beloro@Sun.COM 			rdata = busp->bus_dev_ven_id;
131911596SJason.Beloro@Sun.COM 	}
132010595SShesha.Sreenivasamurthy@Sun.COM 	return ((uint32_t)rdata);
13210Sstevel@tonic-gate }
13220Sstevel@tonic-gate 
13230Sstevel@tonic-gate static void
px_pci_config_put(ddi_acc_impl_t * handle,uint32_t * addr,int size,pci_cfg_data_t wdata)13240Sstevel@tonic-gate px_pci_config_put(ddi_acc_impl_t *handle, uint32_t *addr,
13250Sstevel@tonic-gate 		int size, pci_cfg_data_t wdata)
13260Sstevel@tonic-gate {
13276313Skrishnae 	px_config_acc_pvt_t *px_pvt = (px_config_acc_pvt_t *)
13286313Skrishnae 	    handle->ahi_common.ah_bus_private;
13290Sstevel@tonic-gate 	uint32_t pci_dev_addr = px_pvt->raddr;
13300Sstevel@tonic-gate 	uint32_t vaddr = px_pvt->vaddr;
1331671Skrishnae 	uint16_t off = (uint16_t)(uintptr_t)(addr - vaddr) & 0xfff;
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 	if (px_lib_config_put(px_pvt->dip, pci_dev_addr, off,
13346313Skrishnae 	    size, wdata) != DDI_SUCCESS) {
13350Sstevel@tonic-gate 		/*EMPTY*/
13360Sstevel@tonic-gate 		/* XXX update error kstats */
13370Sstevel@tonic-gate 	}
13380Sstevel@tonic-gate }
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate static uint8_t
px_pci_config_get8(ddi_acc_impl_t * handle,uint8_t * addr)13410Sstevel@tonic-gate px_pci_config_get8(ddi_acc_impl_t *handle, uint8_t *addr)
13420Sstevel@tonic-gate {
13430Sstevel@tonic-gate 	return ((uint8_t)px_pci_config_get(handle, (uint32_t *)addr, 1));
13440Sstevel@tonic-gate }
13450Sstevel@tonic-gate 
13460Sstevel@tonic-gate static uint16_t
px_pci_config_get16(ddi_acc_impl_t * handle,uint16_t * addr)13470Sstevel@tonic-gate px_pci_config_get16(ddi_acc_impl_t *handle, uint16_t *addr)
13480Sstevel@tonic-gate {
13490Sstevel@tonic-gate 	return ((uint16_t)px_pci_config_get(handle, (uint32_t *)addr, 2));
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate 
13520Sstevel@tonic-gate static uint32_t
px_pci_config_get32(ddi_acc_impl_t * handle,uint32_t * addr)13530Sstevel@tonic-gate px_pci_config_get32(ddi_acc_impl_t *handle, uint32_t *addr)
13540Sstevel@tonic-gate {
13550Sstevel@tonic-gate 	return ((uint32_t)px_pci_config_get(handle, (uint32_t *)addr, 4));
13560Sstevel@tonic-gate }
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate static uint64_t
px_pci_config_get64(ddi_acc_impl_t * handle,uint64_t * addr)13590Sstevel@tonic-gate px_pci_config_get64(ddi_acc_impl_t *handle, uint64_t *addr)
13600Sstevel@tonic-gate {
13610Sstevel@tonic-gate 	uint32_t rdatah, rdatal;
13620Sstevel@tonic-gate 
13630Sstevel@tonic-gate 	rdatal = (uint32_t)px_pci_config_get(handle, (uint32_t *)addr, 4);
13640Sstevel@tonic-gate 	rdatah = (uint32_t)px_pci_config_get(handle,
13656313Skrishnae 	    (uint32_t *)((char *)addr+4), 4);
13660Sstevel@tonic-gate 	return (((uint64_t)rdatah << 32) | rdatal);
13670Sstevel@tonic-gate }
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate static void
px_pci_config_put8(ddi_acc_impl_t * handle,uint8_t * addr,uint8_t data)13700Sstevel@tonic-gate px_pci_config_put8(ddi_acc_impl_t *handle, uint8_t *addr, uint8_t data)
13710Sstevel@tonic-gate {
13720Sstevel@tonic-gate 	pci_cfg_data_t wdata = { 0 };
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 	wdata.qw = (uint8_t)data;
13750Sstevel@tonic-gate 	px_pci_config_put(handle, (uint32_t *)addr, 1, wdata);
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate static void
px_pci_config_put16(ddi_acc_impl_t * handle,uint16_t * addr,uint16_t data)13790Sstevel@tonic-gate px_pci_config_put16(ddi_acc_impl_t *handle, uint16_t *addr, uint16_t data)
13800Sstevel@tonic-gate {
13810Sstevel@tonic-gate 	pci_cfg_data_t wdata = { 0 };
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 	wdata.qw = (uint16_t)data;
13840Sstevel@tonic-gate 	px_pci_config_put(handle, (uint32_t *)addr, 2, wdata);
13850Sstevel@tonic-gate }
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate static void
px_pci_config_put32(ddi_acc_impl_t * handle,uint32_t * addr,uint32_t data)13880Sstevel@tonic-gate px_pci_config_put32(ddi_acc_impl_t *handle, uint32_t *addr, uint32_t data)
13890Sstevel@tonic-gate {
13900Sstevel@tonic-gate 	pci_cfg_data_t wdata = { 0 };
13910Sstevel@tonic-gate 
13920Sstevel@tonic-gate 	wdata.qw = (uint32_t)data;
13930Sstevel@tonic-gate 	px_pci_config_put(handle, (uint32_t *)addr, 4, wdata);
13940Sstevel@tonic-gate }
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate static void
px_pci_config_put64(ddi_acc_impl_t * handle,uint64_t * addr,uint64_t data)13970Sstevel@tonic-gate px_pci_config_put64(ddi_acc_impl_t *handle, uint64_t *addr, uint64_t data)
13980Sstevel@tonic-gate {
13990Sstevel@tonic-gate 	pci_cfg_data_t wdata = { 0 };
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 	wdata.qw = (uint32_t)(data & 0xffffffff);
14020Sstevel@tonic-gate 	px_pci_config_put(handle, (uint32_t *)addr, 4, wdata);
14030Sstevel@tonic-gate 	wdata.qw = (uint32_t)((data >> 32) & 0xffffffff);
14040Sstevel@tonic-gate 	px_pci_config_put(handle, (uint32_t *)((char *)addr+4), 4, wdata);
14050Sstevel@tonic-gate }
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate static void
px_pci_config_rep_get8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)14080Sstevel@tonic-gate px_pci_config_rep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
14090Sstevel@tonic-gate 			uint8_t *dev_addr, size_t repcount, uint_t flags)
14100Sstevel@tonic-gate {
14110Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
14120Sstevel@tonic-gate 		for (; repcount; repcount--)
14130Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get8(handle, dev_addr++);
14140Sstevel@tonic-gate 	else
14150Sstevel@tonic-gate 		for (; repcount; repcount--)
14160Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get8(handle, dev_addr);
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate 
14190Sstevel@tonic-gate /*
14200Sstevel@tonic-gate  * Function to rep read 16 bit data off the PCI configuration space behind
14210Sstevel@tonic-gate  * the 21554's host interface.
14220Sstevel@tonic-gate  */
14230Sstevel@tonic-gate static void
px_pci_config_rep_get16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)14240Sstevel@tonic-gate px_pci_config_rep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
14250Sstevel@tonic-gate 			uint16_t *dev_addr, size_t repcount, uint_t flags)
14260Sstevel@tonic-gate {
14270Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
14280Sstevel@tonic-gate 		for (; repcount; repcount--)
14290Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get16(handle, dev_addr++);
14300Sstevel@tonic-gate 	else
14310Sstevel@tonic-gate 		for (; repcount; repcount--)
14320Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get16(handle, dev_addr);
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate 
14350Sstevel@tonic-gate /*
14360Sstevel@tonic-gate  * Function to rep read 32 bit data off the PCI configuration space behind
14370Sstevel@tonic-gate  * the 21554's host interface.
14380Sstevel@tonic-gate  */
14390Sstevel@tonic-gate static void
px_pci_config_rep_get32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)14400Sstevel@tonic-gate px_pci_config_rep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
14410Sstevel@tonic-gate 			uint32_t *dev_addr, size_t repcount, uint_t flags)
14420Sstevel@tonic-gate {
14430Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
14440Sstevel@tonic-gate 		for (; repcount; repcount--)
14450Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get32(handle, dev_addr++);
14460Sstevel@tonic-gate 	else
14470Sstevel@tonic-gate 		for (; repcount; repcount--)
14480Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get32(handle, dev_addr);
14490Sstevel@tonic-gate }
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate /*
14520Sstevel@tonic-gate  * Function to rep read 64 bit data off the PCI configuration space behind
14530Sstevel@tonic-gate  * the 21554's host interface.
14540Sstevel@tonic-gate  */
14550Sstevel@tonic-gate static void
px_pci_config_rep_get64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)14560Sstevel@tonic-gate px_pci_config_rep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
14570Sstevel@tonic-gate 			uint64_t *dev_addr, size_t repcount, uint_t flags)
14580Sstevel@tonic-gate {
14590Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
14600Sstevel@tonic-gate 		for (; repcount; repcount--)
14610Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get64(handle, dev_addr++);
14620Sstevel@tonic-gate 	else
14630Sstevel@tonic-gate 		for (; repcount; repcount--)
14640Sstevel@tonic-gate 			*host_addr++ = px_pci_config_get64(handle, dev_addr);
14650Sstevel@tonic-gate }
14660Sstevel@tonic-gate 
14670Sstevel@tonic-gate /*
14680Sstevel@tonic-gate  * Function to rep write 8 bit data into the PCI configuration space behind
14690Sstevel@tonic-gate  * the 21554's host interface.
14700Sstevel@tonic-gate  */
14710Sstevel@tonic-gate static void
px_pci_config_rep_put8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)14720Sstevel@tonic-gate px_pci_config_rep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
14730Sstevel@tonic-gate 			uint8_t *dev_addr, size_t repcount, uint_t flags)
14740Sstevel@tonic-gate {
14750Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
14760Sstevel@tonic-gate 		for (; repcount; repcount--)
14770Sstevel@tonic-gate 			px_pci_config_put8(handle, dev_addr++, *host_addr++);
14780Sstevel@tonic-gate 	else
14790Sstevel@tonic-gate 		for (; repcount; repcount--)
14800Sstevel@tonic-gate 			px_pci_config_put8(handle, dev_addr, *host_addr++);
14810Sstevel@tonic-gate }
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate /*
14840Sstevel@tonic-gate  * Function to rep write 16 bit data into the PCI configuration space behind
14850Sstevel@tonic-gate  * the 21554's host interface.
14860Sstevel@tonic-gate  */
14870Sstevel@tonic-gate static void
px_pci_config_rep_put16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)14880Sstevel@tonic-gate px_pci_config_rep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
14890Sstevel@tonic-gate 			uint16_t *dev_addr, size_t repcount, uint_t flags)
14900Sstevel@tonic-gate {
14910Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
14920Sstevel@tonic-gate 		for (; repcount; repcount--)
14930Sstevel@tonic-gate 			px_pci_config_put16(handle, dev_addr++, *host_addr++);
14940Sstevel@tonic-gate 	else
14950Sstevel@tonic-gate 		for (; repcount; repcount--)
14960Sstevel@tonic-gate 			px_pci_config_put16(handle, dev_addr, *host_addr++);
14970Sstevel@tonic-gate }
14980Sstevel@tonic-gate 
14990Sstevel@tonic-gate /*
15000Sstevel@tonic-gate  * Function to rep write 32 bit data into the PCI configuration space behind
15010Sstevel@tonic-gate  * the 21554's host interface.
15020Sstevel@tonic-gate  */
15030Sstevel@tonic-gate static void
px_pci_config_rep_put32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)15040Sstevel@tonic-gate px_pci_config_rep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
15050Sstevel@tonic-gate 			uint32_t *dev_addr, size_t repcount, uint_t flags)
15060Sstevel@tonic-gate {
15070Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
15080Sstevel@tonic-gate 		for (; repcount; repcount--)
15090Sstevel@tonic-gate 			px_pci_config_put32(handle, dev_addr++, *host_addr++);
15100Sstevel@tonic-gate 	else
15110Sstevel@tonic-gate 		for (; repcount; repcount--)
15120Sstevel@tonic-gate 			px_pci_config_put32(handle, dev_addr, *host_addr++);
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate 
15150Sstevel@tonic-gate /*
15160Sstevel@tonic-gate  * Function to rep write 64 bit data into the PCI configuration space behind
15170Sstevel@tonic-gate  * the 21554's host interface.
15180Sstevel@tonic-gate  */
15190Sstevel@tonic-gate static void
px_pci_config_rep_put64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)15200Sstevel@tonic-gate px_pci_config_rep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
15210Sstevel@tonic-gate 			uint64_t *dev_addr, size_t repcount, uint_t flags)
15220Sstevel@tonic-gate {
15230Sstevel@tonic-gate 	if (flags == DDI_DEV_AUTOINCR)
15240Sstevel@tonic-gate 		for (; repcount; repcount--)
15250Sstevel@tonic-gate 			px_pci_config_put64(handle, dev_addr++, *host_addr++);
15260Sstevel@tonic-gate 	else
15270Sstevel@tonic-gate 		for (; repcount; repcount--)
15280Sstevel@tonic-gate 			px_pci_config_put64(handle, dev_addr, *host_addr++);
15290Sstevel@tonic-gate }
15300Sstevel@tonic-gate 
15310Sstevel@tonic-gate /*
15320Sstevel@tonic-gate  * Provide a private access handle to route config access calls to Hypervisor.
15330Sstevel@tonic-gate  * Beware: Do all error checking for config space accesses before calling
15340Sstevel@tonic-gate  * this function. ie. do error checking from the calling function.
15350Sstevel@tonic-gate  * Due to a lack of meaningful error code in DDI, the gauranteed return of
15360Sstevel@tonic-gate  * DDI_SUCCESS from here makes the code organization readable/easier from
15370Sstevel@tonic-gate  * the generic code.
15380Sstevel@tonic-gate  */
15390Sstevel@tonic-gate /*ARGSUSED*/
15400Sstevel@tonic-gate int
px_lib_map_vconfig(dev_info_t * dip,ddi_map_req_t * mp,pci_config_offset_t off,pci_regspec_t * rp,caddr_t * addrp)15410Sstevel@tonic-gate px_lib_map_vconfig(dev_info_t *dip,
15420Sstevel@tonic-gate 	ddi_map_req_t *mp, pci_config_offset_t off,
15430Sstevel@tonic-gate 	pci_regspec_t *rp, caddr_t *addrp)
15440Sstevel@tonic-gate {
15456313Skrishnae 	int fmcap;
15466313Skrishnae 	ndi_err_t *errp;
15476313Skrishnae 	on_trap_data_t *otp;
15480Sstevel@tonic-gate 	ddi_acc_hdl_t *hp;
15490Sstevel@tonic-gate 	ddi_acc_impl_t *ap;
15500Sstevel@tonic-gate 	uchar_t busnum;	/* bus number */
15510Sstevel@tonic-gate 	uchar_t devnum;	/* device number */
15520Sstevel@tonic-gate 	uchar_t funcnum; /* function number */
15530Sstevel@tonic-gate 	px_config_acc_pvt_t *px_pvt;
15540Sstevel@tonic-gate 
15550Sstevel@tonic-gate 	hp = (ddi_acc_hdl_t *)mp->map_handlep;
15560Sstevel@tonic-gate 	ap = (ddi_acc_impl_t *)hp->ah_platform_private;
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate 	/* Check for mapping teardown operation */
15590Sstevel@tonic-gate 	if ((mp->map_op == DDI_MO_UNMAP) ||
15606313Skrishnae 	    (mp->map_op == DDI_MO_UNLOCK)) {
15610Sstevel@tonic-gate 		/* free up memory allocated for the private access handle. */
15620Sstevel@tonic-gate 		px_pvt = (px_config_acc_pvt_t *)hp->ah_bus_private;
15630Sstevel@tonic-gate 		kmem_free((void *)px_pvt, sizeof (px_config_acc_pvt_t));
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate 		/* unmap operation of PCI IO/config space. */
15660Sstevel@tonic-gate 		return (DDI_SUCCESS);
15670Sstevel@tonic-gate 	}
15680Sstevel@tonic-gate 
15696313Skrishnae 	fmcap = ddi_fm_capable(dip);
15706313Skrishnae 	if (DDI_FM_ACC_ERR_CAP(fmcap)) {
15716313Skrishnae 		errp = ((ddi_acc_impl_t *)hp)->ahi_err;
15726313Skrishnae 		otp = (on_trap_data_t *)errp->err_ontrap;
15736313Skrishnae 		otp->ot_handle = (void *)(hp);
15746313Skrishnae 		otp->ot_prot = OT_DATA_ACCESS;
15756313Skrishnae 		errp->err_status = DDI_FM_OK;
15766313Skrishnae 		errp->err_expected = DDI_FM_ERR_UNEXPECTED;
15776313Skrishnae 		errp->err_cf = px_err_cfg_hdl_check;
15786313Skrishnae 	}
15796313Skrishnae 
15800Sstevel@tonic-gate 	ap->ahi_get8 = px_pci_config_get8;
15810Sstevel@tonic-gate 	ap->ahi_get16 = px_pci_config_get16;
15820Sstevel@tonic-gate 	ap->ahi_get32 = px_pci_config_get32;
15830Sstevel@tonic-gate 	ap->ahi_get64 = px_pci_config_get64;
15840Sstevel@tonic-gate 	ap->ahi_put8 = px_pci_config_put8;
15850Sstevel@tonic-gate 	ap->ahi_put16 = px_pci_config_put16;
15860Sstevel@tonic-gate 	ap->ahi_put32 = px_pci_config_put32;
15870Sstevel@tonic-gate 	ap->ahi_put64 = px_pci_config_put64;
15880Sstevel@tonic-gate 	ap->ahi_rep_get8 = px_pci_config_rep_get8;
15890Sstevel@tonic-gate 	ap->ahi_rep_get16 = px_pci_config_rep_get16;
15900Sstevel@tonic-gate 	ap->ahi_rep_get32 = px_pci_config_rep_get32;
15910Sstevel@tonic-gate 	ap->ahi_rep_get64 = px_pci_config_rep_get64;
15920Sstevel@tonic-gate 	ap->ahi_rep_put8 = px_pci_config_rep_put8;
15930Sstevel@tonic-gate 	ap->ahi_rep_put16 = px_pci_config_rep_put16;
15940Sstevel@tonic-gate 	ap->ahi_rep_put32 = px_pci_config_rep_put32;
15950Sstevel@tonic-gate 	ap->ahi_rep_put64 = px_pci_config_rep_put64;
15960Sstevel@tonic-gate 
15970Sstevel@tonic-gate 	/* Initialize to default check/notify functions */
15980Sstevel@tonic-gate 	ap->ahi_fault = 0;
15990Sstevel@tonic-gate 	ap->ahi_fault_check = i_ddi_acc_fault_check;
16000Sstevel@tonic-gate 	ap->ahi_fault_notify = i_ddi_acc_fault_notify;
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 	/* allocate memory for our private handle */
16030Sstevel@tonic-gate 	px_pvt = (px_config_acc_pvt_t *)
16046313Skrishnae 	    kmem_zalloc(sizeof (px_config_acc_pvt_t), KM_SLEEP);
16050Sstevel@tonic-gate 	hp->ah_bus_private = (void *)px_pvt;
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate 	busnum = PCI_REG_BUS_G(rp->pci_phys_hi);
16080Sstevel@tonic-gate 	devnum = PCI_REG_DEV_G(rp->pci_phys_hi);
16090Sstevel@tonic-gate 	funcnum = PCI_REG_FUNC_G(rp->pci_phys_hi);
16100Sstevel@tonic-gate 
16110Sstevel@tonic-gate 	/* set up private data for use during IO routines */
16120Sstevel@tonic-gate 
16130Sstevel@tonic-gate 	/* addr needed by the HV APIs */
16140Sstevel@tonic-gate 	px_pvt->raddr = busnum << 16 | devnum << 11 | funcnum << 8;
16150Sstevel@tonic-gate 	/*
16160Sstevel@tonic-gate 	 * Address that specifies the actual offset into the 256MB
16170Sstevel@tonic-gate 	 * memory mapped configuration space, 4K per device.
16180Sstevel@tonic-gate 	 * First 12bits form the offset into 4K config space.
16190Sstevel@tonic-gate 	 * This address is only used during the IO routines to calculate
16200Sstevel@tonic-gate 	 * the offset at which the transaction must be performed.
16210Sstevel@tonic-gate 	 * Drivers bypassing DDI functions to access PCI config space will
16220Sstevel@tonic-gate 	 * panic the system since the following is a bogus virtual address.
16230Sstevel@tonic-gate 	 */
16240Sstevel@tonic-gate 	px_pvt->vaddr = busnum << 20 | devnum << 15 | funcnum << 12 | off;
16250Sstevel@tonic-gate 	px_pvt->dip = dip;
16260Sstevel@tonic-gate 
16270Sstevel@tonic-gate 	DBG(DBG_LIB_CFG, dip, "px_config_setup: raddr 0x%x, vaddr 0x%x\n",
16286313Skrishnae 	    px_pvt->raddr, px_pvt->vaddr);
1629671Skrishnae 	*addrp = (caddr_t)(uintptr_t)px_pvt->vaddr;
16300Sstevel@tonic-gate 	return (DDI_SUCCESS);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate 
1633677Sjchu /*ARGSUSED*/
1634677Sjchu void
px_lib_map_attr_check(ddi_map_req_t * mp)1635677Sjchu px_lib_map_attr_check(ddi_map_req_t *mp)
1636677Sjchu {
1637677Sjchu }
1638677Sjchu 
163927Sjchu /*
164027Sjchu  * px_lib_log_safeacc_err:
164127Sjchu  * Imitate a cpu/mem trap call when a peek/poke fails.
164227Sjchu  * This will initiate something similar to px_fm_callback.
164327Sjchu  */
16440Sstevel@tonic-gate static void
px_lib_log_safeacc_err(px_t * px_p,ddi_acc_handle_t handle,int fme_flag,r_addr_t addr)16453274Set142600 px_lib_log_safeacc_err(px_t *px_p, ddi_acc_handle_t handle, int fme_flag,
16463274Set142600     r_addr_t addr)
16470Sstevel@tonic-gate {
16483274Set142600 	uint32_t	addr_high, addr_low;
16499921SKrishna.Elango@Sun.COM 	pcie_req_id_t	bdf = PCIE_INVALID_BDF;
165010923SEvan.Yan@Sun.COM 	pci_ranges_t	*ranges_p;
16513274Set142600 	int		range_len, i;
16520Sstevel@tonic-gate 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
16530Sstevel@tonic-gate 	ddi_fm_error_t derr;
16540Sstevel@tonic-gate 
165511596SJason.Beloro@Sun.COM 	if (px_fm_enter(px_p) != DDI_SUCCESS)
165611596SJason.Beloro@Sun.COM 		return;
165711596SJason.Beloro@Sun.COM 
16580Sstevel@tonic-gate 	derr.fme_status = DDI_FM_NONFATAL;
16590Sstevel@tonic-gate 	derr.fme_version = DDI_FME_VERSION;
16600Sstevel@tonic-gate 	derr.fme_flag = fme_flag;
16610Sstevel@tonic-gate 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
16620Sstevel@tonic-gate 	derr.fme_acc_handle = handle;
16630Sstevel@tonic-gate 	if (hp)
16640Sstevel@tonic-gate 		hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED;
16650Sstevel@tonic-gate 
16663274Set142600 	addr_high = (uint32_t)(addr >> 32);
16673274Set142600 	addr_low = (uint32_t)addr;
16683274Set142600 
16693274Set142600 	/*
16703274Set142600 	 * Make sure this failed load came from this PCIe port.  Check by
16713274Set142600 	 * matching the upper 32 bits of the address with the ranges property.
16723274Set142600 	 */
167310923SEvan.Yan@Sun.COM 	range_len = px_p->px_ranges_length / sizeof (pci_ranges_t);
16743274Set142600 	i = 0;
16753274Set142600 	for (ranges_p = px_p->px_ranges_p; i < range_len; i++, ranges_p++) {
16763274Set142600 		if (ranges_p->parent_high == addr_high) {
16773274Set142600 			switch (ranges_p->child_high & PCI_ADDR_MASK) {
16783274Set142600 			case PCI_ADDR_CONFIG:
16793274Set142600 				bdf = (pcie_req_id_t)(addr_low >> 12);
16803274Set142600 				break;
16813274Set142600 			default:
16829921SKrishna.Elango@Sun.COM 				bdf = PCIE_INVALID_BDF;
16833274Set142600 				break;
16843274Set142600 			}
16853274Set142600 			break;
16863274Set142600 		}
16873274Set142600 	}
16883274Set142600 
168911596SJason.Beloro@Sun.COM 	(void) px_rp_en_q(px_p, bdf, addr, NULL);
169011596SJason.Beloro@Sun.COM 	(void) px_scan_fabric(px_p, px_p->px_dip, &derr);
169111596SJason.Beloro@Sun.COM 	px_fm_exit(px_p);
16920Sstevel@tonic-gate }
16930Sstevel@tonic-gate 
16940Sstevel@tonic-gate 
16950Sstevel@tonic-gate #ifdef  DEBUG
16960Sstevel@tonic-gate int	px_peekfault_cnt = 0;
16970Sstevel@tonic-gate int	px_pokefault_cnt = 0;
16980Sstevel@tonic-gate #endif  /* DEBUG */
16990Sstevel@tonic-gate 
17000Sstevel@tonic-gate /*
17010Sstevel@tonic-gate  * Do a safe write to a device.
17020Sstevel@tonic-gate  *
17030Sstevel@tonic-gate  * When this function is given a handle (cautious access), all errors are
17040Sstevel@tonic-gate  * suppressed.
17050Sstevel@tonic-gate  *
17060Sstevel@tonic-gate  * When this function is not given a handle (poke), only Unsupported Request
17070Sstevel@tonic-gate  * and Completer Abort errors are suppressed.
17080Sstevel@tonic-gate  *
17090Sstevel@tonic-gate  * In all cases, all errors are returned in the function return status.
17100Sstevel@tonic-gate  */
17110Sstevel@tonic-gate 
17120Sstevel@tonic-gate int
px_lib_ctlops_poke(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * in_args)17130Sstevel@tonic-gate px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip,
17140Sstevel@tonic-gate     peekpoke_ctlops_t *in_args)
17150Sstevel@tonic-gate {
17160Sstevel@tonic-gate 	px_t *px_p = DIP_TO_STATE(dip);
17170Sstevel@tonic-gate 	px_pec_t *pec_p = px_p->px_pec_p;
171827Sjchu 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
17190Sstevel@tonic-gate 
17200Sstevel@tonic-gate 	size_t repcount = in_args->repcount;
17210Sstevel@tonic-gate 	size_t size = in_args->size;
17220Sstevel@tonic-gate 	uintptr_t dev_addr = in_args->dev_addr;
17230Sstevel@tonic-gate 	uintptr_t host_addr = in_args->host_addr;
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 	int err	= DDI_SUCCESS;
17260Sstevel@tonic-gate 	uint64_t hvio_poke_status;
17270Sstevel@tonic-gate 	uint32_t wrt_stat;
17280Sstevel@tonic-gate 
17290Sstevel@tonic-gate 	r_addr_t ra;
17300Sstevel@tonic-gate 	uint64_t pokeval;
17313503Saa72041 	pcie_req_id_t bdf;
173227Sjchu 
17330Sstevel@tonic-gate 	ra = (r_addr_t)va_to_pa((void *)dev_addr);
17340Sstevel@tonic-gate 	for (; repcount; repcount--) {
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 		switch (size) {
17370Sstevel@tonic-gate 		case sizeof (uint8_t):
17380Sstevel@tonic-gate 			pokeval = *(uint8_t *)host_addr;
17390Sstevel@tonic-gate 			break;
17400Sstevel@tonic-gate 		case sizeof (uint16_t):
17410Sstevel@tonic-gate 			pokeval = *(uint16_t *)host_addr;
17420Sstevel@tonic-gate 			break;
17430Sstevel@tonic-gate 		case sizeof (uint32_t):
17440Sstevel@tonic-gate 			pokeval = *(uint32_t *)host_addr;
17450Sstevel@tonic-gate 			break;
17460Sstevel@tonic-gate 		case sizeof (uint64_t):
17470Sstevel@tonic-gate 			pokeval = *(uint64_t *)host_addr;
17480Sstevel@tonic-gate 			break;
17490Sstevel@tonic-gate 		default:
17500Sstevel@tonic-gate 			DBG(DBG_MAP, px_p->px_dip,
17510Sstevel@tonic-gate 			    "poke: invalid size %d passed\n", size);
17520Sstevel@tonic-gate 			err = DDI_FAILURE;
17530Sstevel@tonic-gate 			goto done;
17540Sstevel@tonic-gate 		}
17550Sstevel@tonic-gate 
175627Sjchu 		/*
175727Sjchu 		 * Grab pokefault mutex since hypervisor does not guarantee
175827Sjchu 		 * poke serialization.
175927Sjchu 		 */
176027Sjchu 		if (hp) {
176127Sjchu 			i_ndi_busop_access_enter(hp->ahi_common.ah_dip,
176227Sjchu 			    (ddi_acc_handle_t)hp);
176327Sjchu 			pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
176427Sjchu 		} else {
176527Sjchu 			mutex_enter(&pec_p->pec_pokefault_mutex);
176627Sjchu 			pec_p->pec_safeacc_type = DDI_FM_ERR_POKE;
176727Sjchu 		}
17683503Saa72041 
17693503Saa72041 		if (pcie_get_bdf_from_dip(rdip, &bdf) != DDI_SUCCESS) {
17703503Saa72041 			err = DDI_FAILURE;
17713503Saa72041 			goto done;
17723503Saa72041 		}
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate 		hvio_poke_status = hvio_poke(px_p->px_dev_hdl, ra, size,
17753503Saa72041 		    pokeval, bdf << 8, &wrt_stat);
17760Sstevel@tonic-gate 
17770Sstevel@tonic-gate 		if ((hvio_poke_status != H_EOK) || (wrt_stat != H_EOK)) {
17780Sstevel@tonic-gate 			err = DDI_FAILURE;
17790Sstevel@tonic-gate #ifdef  DEBUG
17800Sstevel@tonic-gate 			px_pokefault_cnt++;
17810Sstevel@tonic-gate #endif
17820Sstevel@tonic-gate 			/*
17830Sstevel@tonic-gate 			 * For CAUTIOUS and POKE access, notify FMA to
178427Sjchu 			 * cleanup.  Imitate a cpu/mem trap call like in sun4u.
17850Sstevel@tonic-gate 			 */
178627Sjchu 			px_lib_log_safeacc_err(px_p, (ddi_acc_handle_t)hp,
178727Sjchu 			    (hp ? DDI_FM_ERR_EXPECTED :
17883274Set142600 			    DDI_FM_ERR_POKE), ra);
17890Sstevel@tonic-gate 
179027Sjchu 			pec_p->pec_ontrap_data = NULL;
179127Sjchu 			pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
179227Sjchu 			if (hp) {
179327Sjchu 				i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
179427Sjchu 				    (ddi_acc_handle_t)hp);
179527Sjchu 			} else {
179627Sjchu 				mutex_exit(&pec_p->pec_pokefault_mutex);
179727Sjchu 			}
17980Sstevel@tonic-gate 			goto done;
17990Sstevel@tonic-gate 		}
18000Sstevel@tonic-gate 
180127Sjchu 		pec_p->pec_ontrap_data = NULL;
180227Sjchu 		pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
180327Sjchu 		if (hp) {
180427Sjchu 			i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
180527Sjchu 			    (ddi_acc_handle_t)hp);
180627Sjchu 		} else {
180727Sjchu 			mutex_exit(&pec_p->pec_pokefault_mutex);
180827Sjchu 		}
180927Sjchu 
18100Sstevel@tonic-gate 		host_addr += size;
18110Sstevel@tonic-gate 
18120Sstevel@tonic-gate 		if (in_args->flags == DDI_DEV_AUTOINCR) {
18130Sstevel@tonic-gate 			dev_addr += size;
18140Sstevel@tonic-gate 			ra = (r_addr_t)va_to_pa((void *)dev_addr);
18150Sstevel@tonic-gate 		}
18160Sstevel@tonic-gate 	}
18170Sstevel@tonic-gate 
18180Sstevel@tonic-gate done:
18190Sstevel@tonic-gate 	return (err);
18200Sstevel@tonic-gate }
18210Sstevel@tonic-gate 
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate /*ARGSUSED*/
18240Sstevel@tonic-gate int
px_lib_ctlops_peek(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * in_args,void * result)18250Sstevel@tonic-gate px_lib_ctlops_peek(dev_info_t *dip, dev_info_t *rdip,
18260Sstevel@tonic-gate     peekpoke_ctlops_t *in_args, void *result)
18270Sstevel@tonic-gate {
18280Sstevel@tonic-gate 	px_t *px_p = DIP_TO_STATE(dip);
18290Sstevel@tonic-gate 	px_pec_t *pec_p = px_p->px_pec_p;
183027Sjchu 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
18310Sstevel@tonic-gate 
18320Sstevel@tonic-gate 	size_t repcount = in_args->repcount;
18330Sstevel@tonic-gate 	uintptr_t dev_addr = in_args->dev_addr;
18340Sstevel@tonic-gate 	uintptr_t host_addr = in_args->host_addr;
18350Sstevel@tonic-gate 
18360Sstevel@tonic-gate 	r_addr_t ra;
18370Sstevel@tonic-gate 	uint32_t read_status;
18380Sstevel@tonic-gate 	uint64_t hvio_peek_status;
18390Sstevel@tonic-gate 	uint64_t peekval;
184027Sjchu 	int err = DDI_SUCCESS;
18410Sstevel@tonic-gate 
18420Sstevel@tonic-gate 	result = (void *)in_args->host_addr;
18430Sstevel@tonic-gate 
18440Sstevel@tonic-gate 	ra = (r_addr_t)va_to_pa((void *)dev_addr);
18450Sstevel@tonic-gate 	for (; repcount; repcount--) {
18460Sstevel@tonic-gate 
18470Sstevel@tonic-gate 		/* Lock pokefault mutex so read doesn't mask a poke fault. */
184827Sjchu 		if (hp) {
184927Sjchu 			i_ndi_busop_access_enter(hp->ahi_common.ah_dip,
185027Sjchu 			    (ddi_acc_handle_t)hp);
185127Sjchu 			pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
185227Sjchu 		} else {
185327Sjchu 			mutex_enter(&pec_p->pec_pokefault_mutex);
185427Sjchu 			pec_p->pec_safeacc_type = DDI_FM_ERR_PEEK;
185527Sjchu 		}
18560Sstevel@tonic-gate 
18570Sstevel@tonic-gate 		hvio_peek_status = hvio_peek(px_p->px_dev_hdl, ra,
18580Sstevel@tonic-gate 		    in_args->size, &read_status, &peekval);
18590Sstevel@tonic-gate 
18600Sstevel@tonic-gate 		if ((hvio_peek_status != H_EOK) || (read_status != H_EOK)) {
18610Sstevel@tonic-gate 			err = DDI_FAILURE;
18620Sstevel@tonic-gate 
18630Sstevel@tonic-gate 			/*
18640Sstevel@tonic-gate 			 * For CAUTIOUS and PEEK access, notify FMA to
186527Sjchu 			 * cleanup.  Imitate a cpu/mem trap call like in sun4u.
18660Sstevel@tonic-gate 			 */
186727Sjchu 			px_lib_log_safeacc_err(px_p, (ddi_acc_handle_t)hp,
186827Sjchu 			    (hp ? DDI_FM_ERR_EXPECTED :
18693274Set142600 			    DDI_FM_ERR_PEEK), ra);
18700Sstevel@tonic-gate 
18710Sstevel@tonic-gate 			/* Stuff FFs in host addr if peek. */
187227Sjchu 			if (hp == NULL) {
18730Sstevel@tonic-gate 				int i;
18740Sstevel@tonic-gate 				uint8_t *ff_addr = (uint8_t *)host_addr;
18750Sstevel@tonic-gate 				for (i = 0; i < in_args->size; i++)
18760Sstevel@tonic-gate 					*ff_addr++ = 0xff;
18770Sstevel@tonic-gate 			}
18780Sstevel@tonic-gate #ifdef  DEBUG
18790Sstevel@tonic-gate 			px_peekfault_cnt++;
18800Sstevel@tonic-gate #endif
188127Sjchu 			pec_p->pec_ontrap_data = NULL;
188227Sjchu 			pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
188327Sjchu 			if (hp) {
188427Sjchu 				i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
188527Sjchu 				    (ddi_acc_handle_t)hp);
188627Sjchu 			} else {
188727Sjchu 				mutex_exit(&pec_p->pec_pokefault_mutex);
188827Sjchu 			}
18890Sstevel@tonic-gate 			goto done;
18900Sstevel@tonic-gate 
189127Sjchu 		}
189227Sjchu 		pec_p->pec_ontrap_data = NULL;
189327Sjchu 		pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
189427Sjchu 		if (hp) {
189527Sjchu 			i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
189627Sjchu 			    (ddi_acc_handle_t)hp);
18970Sstevel@tonic-gate 		} else {
189827Sjchu 			mutex_exit(&pec_p->pec_pokefault_mutex);
189927Sjchu 		}
19000Sstevel@tonic-gate 
190127Sjchu 		switch (in_args->size) {
190227Sjchu 		case sizeof (uint8_t):
190327Sjchu 			*(uint8_t *)host_addr = (uint8_t)peekval;
190427Sjchu 			break;
190527Sjchu 		case sizeof (uint16_t):
190627Sjchu 			*(uint16_t *)host_addr = (uint16_t)peekval;
190727Sjchu 			break;
190827Sjchu 		case sizeof (uint32_t):
190927Sjchu 			*(uint32_t *)host_addr = (uint32_t)peekval;
191027Sjchu 			break;
191127Sjchu 		case sizeof (uint64_t):
191227Sjchu 			*(uint64_t *)host_addr = (uint64_t)peekval;
191327Sjchu 			break;
191427Sjchu 		default:
191527Sjchu 			DBG(DBG_MAP, px_p->px_dip,
191627Sjchu 			    "peek: invalid size %d passed\n",
191727Sjchu 			    in_args->size);
191827Sjchu 			err = DDI_FAILURE;
191927Sjchu 			goto done;
19200Sstevel@tonic-gate 		}
19210Sstevel@tonic-gate 
19220Sstevel@tonic-gate 		host_addr += in_args->size;
19230Sstevel@tonic-gate 
19240Sstevel@tonic-gate 		if (in_args->flags == DDI_DEV_AUTOINCR) {
19250Sstevel@tonic-gate 			dev_addr += in_args->size;
19260Sstevel@tonic-gate 			ra = (r_addr_t)va_to_pa((void *)dev_addr);
19270Sstevel@tonic-gate 		}
19280Sstevel@tonic-gate 	}
19290Sstevel@tonic-gate done:
19300Sstevel@tonic-gate 	return (err);
19310Sstevel@tonic-gate }
19320Sstevel@tonic-gate 
193327Sjchu 
193427Sjchu /* add interrupt vector */
193527Sjchu int
px_err_add_intr(px_fault_t * px_fault_p)193627Sjchu px_err_add_intr(px_fault_t *px_fault_p)
193727Sjchu {
193827Sjchu 	px_t	*px_p = DIP_TO_STATE(px_fault_p->px_fh_dip);
193927Sjchu 
194027Sjchu 	DBG(DBG_LIB_INT, px_p->px_dip,
194127Sjchu 	    "px_err_add_intr: calling add_ivintr");
194227Sjchu 
19432973Sgovinda 	VERIFY(add_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL,
19442973Sgovinda 	    (intrfunc)px_fault_p->px_err_func, (caddr_t)px_fault_p, NULL,
19452973Sgovinda 	    (caddr_t)&px_fault_p->px_intr_payload[0]) == 0);
194627Sjchu 
194727Sjchu 	DBG(DBG_LIB_INT, px_p->px_dip,
194827Sjchu 	    "px_err_add_intr: ib_intr_enable ");
194927Sjchu 
195027Sjchu 	px_ib_intr_enable(px_p, intr_dist_cpuid(), px_fault_p->px_intr_ino);
195127Sjchu 
19522973Sgovinda 	return (DDI_SUCCESS);
195327Sjchu }
195427Sjchu 
195527Sjchu /* remove interrupt vector */
195627Sjchu void
px_err_rem_intr(px_fault_t * px_fault_p)195727Sjchu px_err_rem_intr(px_fault_t *px_fault_p)
195827Sjchu {
195927Sjchu 	px_t	*px_p = DIP_TO_STATE(px_fault_p->px_fh_dip);
196027Sjchu 
196127Sjchu 	px_ib_intr_disable(px_p->px_ib_p, px_fault_p->px_intr_ino,
196227Sjchu 	    IB_INTR_WAIT);
1963965Sgovinda 
19642973Sgovinda 	VERIFY(rem_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL) == 0);
196527Sjchu }
196627Sjchu 
19673623Sjchu void
px_cb_intr_redist(void * arg)19683623Sjchu px_cb_intr_redist(void *arg)
19693623Sjchu {
19703623Sjchu 	px_t	*px_p = (px_t *)arg;
19713623Sjchu 	px_ib_intr_dist_en(px_p->px_dip, intr_dist_cpuid(),
19723623Sjchu 	    px_p->px_inos[PX_INTR_XBC], B_FALSE);
19733623Sjchu }
19743623Sjchu 
19751648Sjchu int
px_cb_add_intr(px_fault_t * f_p)19761648Sjchu px_cb_add_intr(px_fault_t *f_p)
19771648Sjchu {
19783623Sjchu 	px_t	*px_p = DIP_TO_STATE(f_p->px_fh_dip);
19793623Sjchu 
19803623Sjchu 	DBG(DBG_LIB_INT, px_p->px_dip,
19813623Sjchu 	    "px_err_add_intr: calling add_ivintr");
19823623Sjchu 
19833623Sjchu 	VERIFY(add_ivintr(f_p->px_fh_sysino, PX_ERR_PIL,
19843623Sjchu 	    (intrfunc)f_p->px_err_func, (caddr_t)f_p, NULL,
19853623Sjchu 	    (caddr_t)&f_p->px_intr_payload[0]) == 0);
19863623Sjchu 
19873623Sjchu 	intr_dist_add(px_cb_intr_redist, px_p);
19883623Sjchu 
19893623Sjchu 	DBG(DBG_LIB_INT, px_p->px_dip,
19903623Sjchu 	    "px_err_add_intr: ib_intr_enable ");
19913623Sjchu 
19923623Sjchu 	px_ib_intr_enable(px_p, intr_dist_cpuid(), f_p->px_intr_ino);
19933623Sjchu 
19943623Sjchu 	return (DDI_SUCCESS);
19951648Sjchu }
19961648Sjchu 
19971648Sjchu void
px_cb_rem_intr(px_fault_t * f_p)19981648Sjchu px_cb_rem_intr(px_fault_t *f_p)
19991648Sjchu {
20003623Sjchu 	intr_dist_rem(px_cb_intr_redist, DIP_TO_STATE(f_p->px_fh_dip));
20011648Sjchu 	px_err_rem_intr(f_p);
20021648Sjchu }
20031648Sjchu 
200427Sjchu #ifdef FMA
200527Sjchu void
px_fill_rc_status(px_fault_t * px_fault_p,pciex_rc_error_regs_t * rc_status)200627Sjchu px_fill_rc_status(px_fault_t *px_fault_p, pciex_rc_error_regs_t *rc_status)
200727Sjchu {
200827Sjchu 	px_pec_err_t	*err_pkt;
200927Sjchu 
201027Sjchu 	err_pkt = (px_pec_err_t *)px_fault_p->px_intr_payload;
201127Sjchu 
201227Sjchu 	/* initialise all the structure members */
201327Sjchu 	rc_status->status_valid = 0;
201427Sjchu 
201527Sjchu 	if (err_pkt->pec_descr.P) {
201627Sjchu 		/* PCI Status Register */
201727Sjchu 		rc_status->pci_err_status = err_pkt->pci_err_status;
201827Sjchu 		rc_status->status_valid |= PCI_ERR_STATUS_VALID;
201927Sjchu 	}
202027Sjchu 
202127Sjchu 	if (err_pkt->pec_descr.E) {
202227Sjchu 		/* PCIe Status Register */
202327Sjchu 		rc_status->pcie_err_status = err_pkt->pcie_err_status;
202427Sjchu 		rc_status->status_valid |= PCIE_ERR_STATUS_VALID;
202527Sjchu 	}
202627Sjchu 
202727Sjchu 	if (err_pkt->pec_descr.U) {
202827Sjchu 		rc_status->ue_status = err_pkt->ue_reg_status;
202927Sjchu 		rc_status->status_valid |= UE_STATUS_VALID;
203027Sjchu 	}
203127Sjchu 
203227Sjchu 	if (err_pkt->pec_descr.H) {
203327Sjchu 		rc_status->ue_hdr1 = err_pkt->hdr[0];
203427Sjchu 		rc_status->status_valid |= UE_HDR1_VALID;
203527Sjchu 	}
203627Sjchu 
203727Sjchu 	if (err_pkt->pec_descr.I) {
203827Sjchu 		rc_status->ue_hdr2 = err_pkt->hdr[1];
203927Sjchu 		rc_status->status_valid |= UE_HDR2_VALID;
204027Sjchu 	}
204127Sjchu 
204227Sjchu 	/* ue_fst_err_ptr - not available for sun4v?? */
204327Sjchu 
204427Sjchu 
204527Sjchu 	if (err_pkt->pec_descr.S) {
204627Sjchu 		rc_status->source_id = err_pkt->err_src_reg;
204727Sjchu 		rc_status->status_valid |= SOURCE_ID_VALID;
204827Sjchu 	}
204927Sjchu 
205027Sjchu 	if (err_pkt->pec_descr.R) {
205127Sjchu 		rc_status->root_err_status = err_pkt->root_err_status;
205227Sjchu 		rc_status->status_valid |= CE_STATUS_VALID;
205327Sjchu 	}
205427Sjchu }
205527Sjchu #endif
205627Sjchu 
20570Sstevel@tonic-gate /*ARGSUSED*/
20580Sstevel@tonic-gate int
px_lib_pmctl(int cmd,px_t * px_p)20590Sstevel@tonic-gate px_lib_pmctl(int cmd, px_t *px_p)
20600Sstevel@tonic-gate {
20610Sstevel@tonic-gate 	return (DDI_FAILURE);
20620Sstevel@tonic-gate }
2063118Sjchu 
2064118Sjchu /*ARGSUSED*/
2065118Sjchu uint_t
px_pmeq_intr(caddr_t arg)2066118Sjchu px_pmeq_intr(caddr_t arg)
2067118Sjchu {
2068118Sjchu 	return (DDI_INTR_CLAIMED);
2069118Sjchu }
2070383Set142600 
2071383Set142600 /*
207211245SZhijun.Fu@Sun.COM  * fetch the config space base addr of the root complex
207311245SZhijun.Fu@Sun.COM  * note this depends on px structure being initialized
2074383Set142600  */
207511245SZhijun.Fu@Sun.COM uint64_t
px_lib_get_cfgacc_base(dev_info_t * dip)207611245SZhijun.Fu@Sun.COM px_lib_get_cfgacc_base(dev_info_t *dip)
207711245SZhijun.Fu@Sun.COM {
207811245SZhijun.Fu@Sun.COM 	int		instance = DIP_TO_INST(dip);
207911245SZhijun.Fu@Sun.COM 	px_t		*px_p = INST_TO_STATE(instance);
2080383Set142600 
208111245SZhijun.Fu@Sun.COM 	return (px_p->px_dev_hdl);
2082383Set142600 }
2083435Sjchu 
208411596SJason.Beloro@Sun.COM void
px_panic_domain(px_t * px_p,pcie_req_id_t bdf)208511596SJason.Beloro@Sun.COM px_panic_domain(px_t *px_p, pcie_req_id_t bdf)
208611596SJason.Beloro@Sun.COM {
208711596SJason.Beloro@Sun.COM 	uint64_t	ret;
208811596SJason.Beloro@Sun.COM 	dev_info_t	*dip = px_p->px_dip;
208911596SJason.Beloro@Sun.COM 
209011596SJason.Beloro@Sun.COM 	DBG(DBG_ERR_INTR, dip, "px_panic_domain: handle 0x%lx, ino %d, "
209111596SJason.Beloro@Sun.COM 	    "bdf<<8 0x%lx\n",
209211596SJason.Beloro@Sun.COM 	    (uint64_t)DIP_TO_HANDLE(dip), px_p->px_cb_fault.px_intr_ino,
209311596SJason.Beloro@Sun.COM 	    (pci_device_t)bdf << 8);
209411596SJason.Beloro@Sun.COM 	if ((ret = pci_error_send(DIP_TO_HANDLE(dip),
209511596SJason.Beloro@Sun.COM 	    px_p->px_cb_fault.px_intr_ino, (pci_device_t)bdf << 8)) != H_EOK) {
209611596SJason.Beloro@Sun.COM 		DBG(DBG_ERR_INTR, dip, "pci_error_send failed, ret 0x%lx\n",
209711596SJason.Beloro@Sun.COM 		    ret);
209811596SJason.Beloro@Sun.COM 	} else
209911596SJason.Beloro@Sun.COM 		DBG(DBG_ERR_INTR, dip, "pci_error_send worked\n");
210011596SJason.Beloro@Sun.COM }
210111596SJason.Beloro@Sun.COM 
21021531Skini /*ARGSUSED*/
21031531Skini int
px_lib_hotplug_init(dev_info_t * dip,void * arg)21041531Skini px_lib_hotplug_init(dev_info_t *dip, void *arg)
21051531Skini {
21061531Skini 	return (DDI_ENOTSUP);
21071531Skini }
21081531Skini 
21091531Skini /*ARGSUSED*/
21101531Skini void
px_lib_hotplug_uninit(dev_info_t * dip)21111531Skini px_lib_hotplug_uninit(dev_info_t *dip)
21121531Skini {
21131531Skini }
21141531Skini 
21153953Sscarter /*ARGSUSED*/
21163953Sscarter void
px_hp_intr_redist(px_t * px_p)21173953Sscarter px_hp_intr_redist(px_t *px_p)
21183953Sscarter {
21193953Sscarter }
21203953Sscarter 
2121435Sjchu /* Dummy cpr add callback */
2122435Sjchu /*ARGSUSED*/
2123435Sjchu void
px_cpr_add_callb(px_t * px_p)2124435Sjchu px_cpr_add_callb(px_t *px_p)
2125435Sjchu {
2126435Sjchu }
2127435Sjchu 
2128435Sjchu /* Dummy cpr rem callback */
2129435Sjchu /*ARGSUSED*/
2130435Sjchu void
px_cpr_rem_callb(px_t * px_p)2131435Sjchu px_cpr_rem_callb(px_t *px_p)
2132435Sjchu {
2133435Sjchu }
21342476Sdwoods 
21352476Sdwoods /*ARGSUSED*/
21362476Sdwoods boolean_t
px_lib_is_in_drain_state(px_t * px_p)21372476Sdwoods px_lib_is_in_drain_state(px_t *px_p)
21382476Sdwoods {
21392476Sdwoods 	return (B_FALSE);
21402476Sdwoods }
21413613Set142600 
21423613Set142600 /*
21433613Set142600  * There is no IOAPI to get the BDF of the pcie root port nexus at this moment.
21443613Set142600  * Assume it is 0x0000, until otherwise noted.  For now, all sun4v platforms
21453613Set142600  * have programmed the BDF to be 0x0000.
21463613Set142600  */
21473613Set142600 /*ARGSUSED*/
21483613Set142600 pcie_req_id_t
px_lib_get_bdf(px_t * px_p)21493613Set142600 px_lib_get_bdf(px_t *px_p)
21503613Set142600 {
21513613Set142600 	return (0x0000);
21523613Set142600 }
21537596SAlan.Adamson@Sun.COM 
21547596SAlan.Adamson@Sun.COM int
px_lib_get_root_complex_mps(px_t * px_p,dev_info_t * dip,int * mps)21557596SAlan.Adamson@Sun.COM px_lib_get_root_complex_mps(px_t *px_p, dev_info_t *dip, int *mps)
21567596SAlan.Adamson@Sun.COM {
21577596SAlan.Adamson@Sun.COM 	pci_device_t	bdf = px_lib_get_bdf(px_p);
21587596SAlan.Adamson@Sun.COM 
21597596SAlan.Adamson@Sun.COM 	if (hvio_get_rp_mps_cap(DIP_TO_HANDLE(dip), bdf, mps) == H_EOK)
21607596SAlan.Adamson@Sun.COM 		return (DDI_SUCCESS);
21617596SAlan.Adamson@Sun.COM 	else
21627596SAlan.Adamson@Sun.COM 		return (DDI_FAILURE);
21637596SAlan.Adamson@Sun.COM }
21647596SAlan.Adamson@Sun.COM 
21657596SAlan.Adamson@Sun.COM int
px_lib_set_root_complex_mps(px_t * px_p,dev_info_t * dip,int mps)21667596SAlan.Adamson@Sun.COM px_lib_set_root_complex_mps(px_t *px_p,  dev_info_t *dip, int mps)
21677596SAlan.Adamson@Sun.COM {
21687596SAlan.Adamson@Sun.COM 	pci_device_t	bdf = px_lib_get_bdf(px_p);
21697596SAlan.Adamson@Sun.COM 
21707596SAlan.Adamson@Sun.COM 	if (hvio_set_rp_mps(DIP_TO_HANDLE(dip), bdf, mps) == H_EOK)
21717596SAlan.Adamson@Sun.COM 		return (DDI_SUCCESS);
21727596SAlan.Adamson@Sun.COM 	else
21737596SAlan.Adamson@Sun.COM 		return (DDI_FAILURE);
21747596SAlan.Adamson@Sun.COM }
217511596SJason.Beloro@Sun.COM 
217611596SJason.Beloro@Sun.COM static int
px_lib_do_count_waiting_dev(dev_info_t * dip,void * arg)217711596SJason.Beloro@Sun.COM px_lib_do_count_waiting_dev(dev_info_t *dip, void *arg)
217811596SJason.Beloro@Sun.COM {
217911596SJason.Beloro@Sun.COM 	int *count = (int *)arg;
218011596SJason.Beloro@Sun.COM 	dev_info_t *cdip = ddi_get_child(dip);
218111596SJason.Beloro@Sun.COM 
218211596SJason.Beloro@Sun.COM 	while (cdip != NULL) {
218311596SJason.Beloro@Sun.COM 		/* check if this is an assigned device */
218411596SJason.Beloro@Sun.COM 		if (ddi_prop_exists(DDI_DEV_T_NONE, cdip, DDI_PROP_DONTPASS,
218511596SJason.Beloro@Sun.COM 		    "ddi-assigned")) {
218611596SJason.Beloro@Sun.COM 			DBG(DBG_ATTACH, dip, "px_lib_do_count_waiting_dev: "
218711596SJason.Beloro@Sun.COM 			    "Found an assigned dev %p, under bridge %p",
218811596SJason.Beloro@Sun.COM 			    cdip, dip);
218911596SJason.Beloro@Sun.COM 
219011596SJason.Beloro@Sun.COM 			/*
219111596SJason.Beloro@Sun.COM 			 * Mark this bridge as needing waiting for
219211596SJason.Beloro@Sun.COM 			 * CHILD_LOANED will be removed after bridge reports
219311596SJason.Beloro@Sun.COM 			 * its readyness back to px driver
219411596SJason.Beloro@Sun.COM 			 */
219511596SJason.Beloro@Sun.COM 			if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
219611596SJason.Beloro@Sun.COM 			    CHILD_LOANED, 1) == DDI_PROP_SUCCESS)
219711596SJason.Beloro@Sun.COM 				(*count)++;
219811596SJason.Beloro@Sun.COM 			break;
219911596SJason.Beloro@Sun.COM 		}
220011596SJason.Beloro@Sun.COM 		cdip = ddi_get_next_sibling(cdip);
220111596SJason.Beloro@Sun.COM 	}
220211596SJason.Beloro@Sun.COM 
220311596SJason.Beloro@Sun.COM 	return (DDI_WALK_CONTINUE);
220411596SJason.Beloro@Sun.COM }
220511596SJason.Beloro@Sun.COM 
220611596SJason.Beloro@Sun.COM static int
px_lib_count_waiting_dev(dev_info_t * dip)220711596SJason.Beloro@Sun.COM px_lib_count_waiting_dev(dev_info_t *dip)
220811596SJason.Beloro@Sun.COM {
220911596SJason.Beloro@Sun.COM 	int circular_count;
221011596SJason.Beloro@Sun.COM 	int count = 0;
221111596SJason.Beloro@Sun.COM 
221211596SJason.Beloro@Sun.COM 	/* No need to continue if this system is not SDIO capable */
221311596SJason.Beloro@Sun.COM 	if (px_sdio_users == 0)
221411596SJason.Beloro@Sun.COM 		return (0);
221511596SJason.Beloro@Sun.COM 
221611596SJason.Beloro@Sun.COM 	/* see if px iteslf has assigned children */
221711596SJason.Beloro@Sun.COM 	(void) px_lib_do_count_waiting_dev(dip, &count);
221811596SJason.Beloro@Sun.COM 
221911596SJason.Beloro@Sun.COM 	/* scan dev under this px */
222011596SJason.Beloro@Sun.COM 	ndi_devi_enter(dip, &circular_count);
222111596SJason.Beloro@Sun.COM 	ddi_walk_devs(ddi_get_child(dip), px_lib_do_count_waiting_dev, &count);
222211596SJason.Beloro@Sun.COM 	ndi_devi_exit(dip, circular_count);
222311596SJason.Beloro@Sun.COM 	return (count);
222411596SJason.Beloro@Sun.COM }
222511596SJason.Beloro@Sun.COM 
222611596SJason.Beloro@Sun.COM /* Called from px/bridge driver directly to report its readyness */
222711596SJason.Beloro@Sun.COM int
px_lib_fabric_sync(dev_info_t * dip)222811596SJason.Beloro@Sun.COM px_lib_fabric_sync(dev_info_t *dip)
222911596SJason.Beloro@Sun.COM {
223011596SJason.Beloro@Sun.COM 	px_t *px;
223111596SJason.Beloro@Sun.COM 	dev_info_t *rcdip;
223211596SJason.Beloro@Sun.COM 	int waitdev;
223311596SJason.Beloro@Sun.COM 
223411596SJason.Beloro@Sun.COM 	/* No need to continue if this system is not SDIO capable */
223511596SJason.Beloro@Sun.COM 	if (px_sdio_users == 0)
223611596SJason.Beloro@Sun.COM 		return (DDI_SUCCESS);
223711596SJason.Beloro@Sun.COM 
223811596SJason.Beloro@Sun.COM 	/* a valid bridge w/ assigned dev under it? */
223911596SJason.Beloro@Sun.COM 	if (ddi_prop_remove(DDI_DEV_T_NONE, dip, CHILD_LOANED) !=
224011596SJason.Beloro@Sun.COM 	    DDI_PROP_SUCCESS)
224111596SJason.Beloro@Sun.COM 		return (DDI_FAILURE);
224211596SJason.Beloro@Sun.COM 
224311596SJason.Beloro@Sun.COM 	/* find out RC dip */
224411596SJason.Beloro@Sun.COM 	for (rcdip = dip; rcdip != NULL; rcdip = ddi_get_parent(rcdip)) {
224511596SJason.Beloro@Sun.COM 		if (PCIE_DIP2BUS(rcdip) && PCIE_IS_RC(PCIE_DIP2BUS(rcdip)))
224611596SJason.Beloro@Sun.COM 			break;
224711596SJason.Beloro@Sun.COM 	}
224811596SJason.Beloro@Sun.COM 	if ((rcdip == NULL) || ((px = (px_t *)DIP_TO_STATE(rcdip)) == NULL))
224911596SJason.Beloro@Sun.COM 		return (DDI_FAILURE);
225011596SJason.Beloro@Sun.COM 
225111596SJason.Beloro@Sun.COM 	/* are we ready? */
225211596SJason.Beloro@Sun.COM 	waitdev = (int)(uintptr_t)px->px_plat_p;
225311596SJason.Beloro@Sun.COM 	ASSERT(waitdev);
225411596SJason.Beloro@Sun.COM 	DBG(DBG_CTLOPS, rcdip, "px_lib_fabric_sync: "
225511596SJason.Beloro@Sun.COM 	    "Px/bridge %p is ready, %d left", rcdip, waitdev - 1);
225611596SJason.Beloro@Sun.COM 	--waitdev;
225711596SJason.Beloro@Sun.COM 	px->px_plat_p = (void *)(uintptr_t)waitdev;
225811596SJason.Beloro@Sun.COM 	if (waitdev != 0)
225911596SJason.Beloro@Sun.COM 		return (DDI_SUCCESS);
226011596SJason.Beloro@Sun.COM 
226111596SJason.Beloro@Sun.COM 	/* notify hpyervisor */
226211596SJason.Beloro@Sun.COM 	DBG(DBG_CTLOPS, rcdip, "px_lib_fabric_sync: "
226311596SJason.Beloro@Sun.COM 	    "Notifying HV that RC %p is ready users=%d", rcdip, px_sdio_users);
226411596SJason.Beloro@Sun.COM 
226511596SJason.Beloro@Sun.COM 	if (pci_iov_root_configured(px->px_dev_hdl) != H_EOK)
226611596SJason.Beloro@Sun.COM 		return (DDI_FAILURE);
226711596SJason.Beloro@Sun.COM 
226811596SJason.Beloro@Sun.COM 	return (DDI_SUCCESS);
226911596SJason.Beloro@Sun.COM }
2270